diff --git a/pyformlang/cfg/tests/test_cfg.py b/pyformlang/cfg/tests/test_cfg.py index 5519171..c0e3cdd 100644 --- a/pyformlang/cfg/tests/test_cfg.py +++ b/pyformlang/cfg/tests/test_cfg.py @@ -1,4 +1,4 @@ -""" Tests the CFG """ +"""Tests the CFG.""" import pytest @@ -12,12 +12,12 @@ class TestCFG: - """ Tests the context free grammar """ + """Tests the context free grammar.""" # pylint: disable=missing-function-docstring, too-many-public-methods - def test_creation(self): - """ Tests creatin of CFG """ + def test_creation(self) -> None: + """Tests creatin of CFG.""" variable0 = Variable(0) terminal0 = Terminal("a") prod0 = Production(variable0, [terminal0, Terminal("A"), Variable(1)]) @@ -35,8 +35,8 @@ def test_creation(self): assert len(cfg.productions) == 0 assert cfg.is_empty() - def test_generating_object(self): - """ Test the finding of CFGObject """ + def test_generating_object(self) -> None: + """Test the finding of CFGObject.""" var_a = Variable("A") var_b = Variable("B") ter_a = Terminal("a") @@ -45,26 +45,35 @@ def test_generating_object(self): prod0 = Production(start, [var_a, var_b]) prod1 = Production(start, [ter_a]) prod2 = Production(var_a, [ter_b]) - cfg = CFG({var_a, var_b, start}, {ter_a, ter_b}, start, - {prod0, prod1, prod2}) + cfg = CFG( + {var_a, var_b, start}, {ter_a, ter_b}, start, {prod0, prod1, prod2} + ) assert len(cfg.variables) == 3 assert len(cfg.terminals) == 2 assert len(cfg.productions) == 3 - assert cfg.get_generating_symbols() == \ - {var_a, ter_a, ter_b, start} + assert cfg.get_generating_symbols() == {var_a, ter_a, ter_b, start} prod3 = Production(var_b, [Epsilon()]) - cfg = CFG({var_a, var_b, start}, {ter_a, ter_b}, start, - {prod0, prod1, prod2, prod3}) + cfg = CFG( + {var_a, var_b, start}, + {ter_a, ter_b}, + start, + {prod0, prod1, prod2, prod3}, + ) assert len(cfg.variables) == 3 assert len(cfg.terminals) == 2 assert len(cfg.productions) == 4 - assert cfg.get_generating_symbols() == {var_a, var_b, ter_a, - ter_b, start} - - def test_reachable_object(self): - """ Test the finding of reachable objects """ + assert cfg.get_generating_symbols() == { + var_a, + var_b, + ter_a, + ter_b, + start, + } + + def test_reachable_object(self) -> None: + """Test the finding of reachable objects.""" var_a = Variable("A") var_b = Variable("B") var_c = Variable("C") @@ -77,14 +86,22 @@ def test_reachable_object(self): prod2 = Production(var_a, [ter_b]) prod3 = Production(var_c, [ter_c]) prod4 = Production(var_a, [Epsilon()]) - cfg = CFG({var_a, var_b, start, var_c}, - {ter_a, ter_b, ter_c}, - start, {prod0, prod1, prod2, prod3, prod4}) - assert cfg.get_reachable_symbols() == {var_a, ter_a, var_b, - ter_b, start} - - def test_useless_removal(self): - """ Test the removal of useless symbols """ + cfg = CFG( + {var_a, var_b, start, var_c}, + {ter_a, ter_b, ter_c}, + start, + {prod0, prod1, prod2, prod3, prod4}, + ) + assert cfg.get_reachable_symbols() == { + var_a, + ter_a, + var_b, + ter_b, + start, + } + + def test_useless_removal(self) -> None: + """Test the removal of useless symbols.""" var_a = Variable("A") var_b = Variable("B") ter_a = Terminal("a") @@ -93,16 +110,17 @@ def test_useless_removal(self): prod0 = Production(start, [var_a, var_b]) prod1 = Production(start, [ter_a]) prod2 = Production(var_a, [ter_b]) - cfg = CFG({var_a, var_b, start}, {ter_a, ter_b}, start, - {prod0, prod1, prod2}) + cfg = CFG( + {var_a, var_b, start}, {ter_a, ter_b}, start, {prod0, prod1, prod2} + ) new_cfg = cfg.remove_useless_symbols() assert len(new_cfg.variables) == 1 assert len(new_cfg.terminals) == 1 assert len(new_cfg.productions) == 1 assert not cfg.is_empty() - def test_nullable_object(self): - """ Tests the finding of nullable objects """ + def test_nullable_object(self) -> None: + """Tests the finding of nullable objects.""" var_a = Variable("A") var_b = Variable("B") ter_a = Terminal("a") @@ -113,14 +131,16 @@ def test_nullable_object(self): prod2 = Production(var_a, [Epsilon()]) prod3 = Production(var_b, [ter_b, var_b, var_b]) prod4 = Production(var_b, [Epsilon()]) - cfg = CFG({var_a, var_b, start}, - {ter_a, ter_b}, - start, {prod0, prod1, prod2, prod3, prod4}) - assert cfg.get_nullable_symbols() == \ - {var_a, var_b, start} - - def test_remove_epsilon(self): - """ Tests the removal of epsilon """ + cfg = CFG( + {var_a, var_b, start}, + {ter_a, ter_b}, + start, + {prod0, prod1, prod2, prod3, prod4}, + ) + assert cfg.get_nullable_symbols() == {var_a, var_b, start} + + def test_remove_epsilon(self) -> None: + """Tests the removal of epsilon.""" var_a = Variable("A") var_b = Variable("B") ter_a = Terminal("a") @@ -131,9 +151,12 @@ def test_remove_epsilon(self): prod2 = Production(var_a, [Epsilon()]) prod3 = Production(var_b, [ter_b, var_b, var_b]) prod4 = Production(var_b, []) - cfg = CFG({var_a, var_b, start}, - {ter_a, ter_b}, - start, {prod0, prod1, prod2, prod3, prod4}) + cfg = CFG( + {var_a, var_b, start}, + {ter_a, ter_b}, + start, + {prod0, prod1, prod2, prod3, prod4}, + ) new_cfg = cfg.remove_epsilon() assert len(new_cfg.variables) == 3 assert len(new_cfg.terminals) == 2 @@ -141,8 +164,8 @@ def test_remove_epsilon(self): assert len(new_cfg.get_nullable_symbols()) == 0 assert not cfg.is_empty() - def test_unit_pair(self): - """ Test the finding of unit pairs """ + def test_unit_pair(self) -> None: + """Test the finding of unit pairs.""" # pylint: disable=too-many-locals var_i = Variable("I") var_f = Variable("F") @@ -156,39 +179,52 @@ def test_unit_pair(self): ter_par_close = Terminal(")") ter_mult = Terminal("*") ter_plus = Terminal("+") - productions = {Production(var_i, [ter_a]), - Production(var_i, [ter_b]), - Production(var_i, [var_i, ter_a]), - Production(var_i, [var_i, ter_b]), - Production(var_i, [var_i, ter_0]), - Production(var_i, [var_i, ter_1]), - Production(var_f, [var_i]), - Production(var_f, [ter_par_open, var_e, ter_par_close]), - Production(var_t, [var_f]), - Production(var_t, [var_t, ter_mult, var_f]), - Production(var_e, [var_t]), - Production(var_e, [var_e, ter_plus, var_t])} - cfg = CFG({var_i, var_f, var_e, var_t}, - {ter_a, ter_b, ter_0, ter_1, ter_par_open, - ter_par_close, ter_mult, ter_plus}, - var_e, - productions) - assert cfg.get_unit_pairs() == \ - {(var_e, var_e), - (var_e, var_t), - (var_e, var_f), - (var_e, var_i), - (var_t, var_t), - (var_t, var_f), - (var_t, var_i), - (var_f, var_f), - (var_f, var_i), - (var_i, var_i)} + productions = { + Production(var_i, [ter_a]), + Production(var_i, [ter_b]), + Production(var_i, [var_i, ter_a]), + Production(var_i, [var_i, ter_b]), + Production(var_i, [var_i, ter_0]), + Production(var_i, [var_i, ter_1]), + Production(var_f, [var_i]), + Production(var_f, [ter_par_open, var_e, ter_par_close]), + Production(var_t, [var_f]), + Production(var_t, [var_t, ter_mult, var_f]), + Production(var_e, [var_t]), + Production(var_e, [var_e, ter_plus, var_t]), + } + cfg = CFG( + {var_i, var_f, var_e, var_t}, + { + ter_a, + ter_b, + ter_0, + ter_1, + ter_par_open, + ter_par_close, + ter_mult, + ter_plus, + }, + var_e, + productions, + ) + assert cfg.get_unit_pairs() == { + (var_e, var_e), + (var_e, var_t), + (var_e, var_f), + (var_e, var_i), + (var_t, var_t), + (var_t, var_f), + (var_t, var_i), + (var_f, var_f), + (var_f, var_i), + (var_i, var_i), + } new_cfg = cfg.eliminate_unit_productions() assert len(set(new_cfg.productions)) == 30 - def test_cnf(self): - """ Tests the conversion to CNF form """ + def test_cnf(self) -> None: + """Tests the conversion to CNF form.""" # pylint: disable=too-many-locals var_i = Variable("I") var_f = Variable("F") @@ -202,23 +238,35 @@ def test_cnf(self): ter_par_close = Terminal(")") ter_mult = Terminal("*") ter_plus = Terminal("+") - productions = {Production(var_i, [ter_a]), - Production(var_i, [ter_b]), - Production(var_i, [var_i, ter_a]), - Production(var_i, [var_i, ter_b]), - Production(var_i, [var_i, ter_0]), - Production(var_i, [var_i, ter_1]), - Production(var_f, [var_i]), - Production(var_f, [ter_par_open, var_e, ter_par_close]), - Production(var_t, [var_f]), - Production(var_t, [var_t, ter_mult, var_f]), - Production(var_e, [var_t]), - Production(var_e, [var_e, ter_plus, var_t])} - cfg = CFG({var_i, var_f, var_e, var_t}, - {ter_a, ter_b, ter_0, ter_1, ter_par_open, - ter_par_close, ter_mult, ter_plus}, - var_e, - productions) + productions = { + Production(var_i, [ter_a]), + Production(var_i, [ter_b]), + Production(var_i, [var_i, ter_a]), + Production(var_i, [var_i, ter_b]), + Production(var_i, [var_i, ter_0]), + Production(var_i, [var_i, ter_1]), + Production(var_f, [var_i]), + Production(var_f, [ter_par_open, var_e, ter_par_close]), + Production(var_t, [var_f]), + Production(var_t, [var_t, ter_mult, var_f]), + Production(var_e, [var_t]), + Production(var_e, [var_e, ter_plus, var_t]), + } + cfg = CFG( + {var_i, var_f, var_e, var_t}, + { + ter_a, + ter_b, + ter_0, + ter_1, + ter_par_open, + ter_par_close, + ter_mult, + ter_plus, + }, + var_e, + productions, + ) new_cfg = cfg.to_normal_form() assert len(new_cfg.variables) == 15 assert len(new_cfg.terminals) == 8 @@ -227,16 +275,15 @@ def test_cnf(self): new_cfg2 = cfg.to_normal_form() assert new_cfg.productions == new_cfg2.productions - cfg2 = CFG(start_symbol=var_e, - productions={Production(var_e, [var_t])}) + cfg2 = CFG(start_symbol=var_e, productions={Production(var_e, [var_t])}) new_cfg = cfg2.to_normal_form() assert len(new_cfg.variables) == 1 assert len(new_cfg.terminals) == 0 assert len(new_cfg.productions) == 0 assert cfg2.is_empty() - def test_substitution(self): - """ Tests substitutions in a CFG """ + def test_substitution(self) -> None: + """Tests substitutions in a CFG.""" var_s = Variable("S") ter_a = Terminal("a") ter_b = Terminal("b") @@ -250,8 +297,8 @@ def test_substitution(self): assert not new_cfg.is_empty() assert new_cfg.contains([ter_a, ter_b, ter_a, ter_b, ter_b, ter_b]) - def test_union(self): - """ Tests the union of two cfg """ + def test_union(self) -> None: + """Tests the union of two cfg.""" var_s = Variable("S") ter_a = Terminal("a") ter_b = Terminal("b") @@ -265,8 +312,8 @@ def test_union(self): assert not new_cfg.is_empty() assert new_cfg.contains([ter_a, ter_a, ter_b, ter_b]) - def test_concatenation(self): - """ Tests the concatenation of two cfg """ + def test_concatenation(self) -> None: + """Tests the concatenation of two cfg.""" var_s = Variable("S") ter_a = Terminal("a") ter_b = Terminal("b") @@ -280,8 +327,8 @@ def test_concatenation(self): assert not new_cfg.is_empty() assert new_cfg.contains([ter_a, ter_a, ter_b, ter_b, ter_a, ter_b]) - def test_closure(self): - """ Tests the closure of a cfg """ + def test_closure(self) -> None: + """Tests the closure of a cfg.""" var_s = Variable("S") ter_a = Terminal("a") ter_b = Terminal("b") @@ -295,11 +342,12 @@ def test_closure(self): assert len(new_cfg.productions) == 5 assert not new_cfg.is_empty() assert new_cfg.contains([]) - assert new_cfg.contains([ter_a, ter_a, ter_c, ter_b, ter_b, - ter_a, ter_c, ter_b]) + assert new_cfg.contains( + [ter_a, ter_a, ter_c, ter_b, ter_b, ter_a, ter_c, ter_b] + ) - def test_pos_closure(self): - """ Tests the closure of a cfg """ + def test_pos_closure(self) -> None: + """Tests the closure of a cfg.""" var_s = Variable("S") ter_a = Terminal("a") ter_b = Terminal("b") @@ -313,11 +361,12 @@ def test_pos_closure(self): assert len(new_cfg.productions) == 6 assert not new_cfg.is_empty() assert not new_cfg.contains([]) - assert new_cfg.contains([ter_a, ter_a, ter_c, ter_b, ter_b, - ter_a, ter_c, ter_b]) + assert new_cfg.contains( + [ter_a, ter_a, ter_c, ter_b, ter_b, ter_a, ter_c, ter_b] + ) - def test_reverse(self): - """ Test the reversal of a CFG """ + def test_reverse(self) -> None: + """Test the reversal of a CFG.""" var_s = Variable("S") ter_a = Terminal("a") ter_b = Terminal("b") @@ -328,11 +377,11 @@ def test_reverse(self): assert len(new_cfg.variables) == 1 assert len(new_cfg.terminals) == 2 assert len(new_cfg.productions) == 2 - assert not (not new_cfg) + assert new_cfg assert new_cfg.contains([ter_b, ter_b, ter_a, ter_a]) - def test_emptiness(self): - """ Tests the emptiness of a CFG """ + def test_emptiness(self) -> None: + """Tests the emptiness of a CFG.""" # pylint: disable=too-many-locals var_s = Variable("S") ter_a = Terminal("a") @@ -342,8 +391,8 @@ def test_emptiness(self): cfg = CFG({var_s}, {ter_a, ter_b}, var_s, {prod0, prod1}) assert not cfg.is_empty() - def test_membership(self): - """ Tests the membership of a CFG """ + def test_membership(self) -> None: + """Tests the membership of a CFG.""" # pylint: disable=too-many-locals var_useless = Variable("USELESS") var_s = Variable("S") @@ -356,13 +405,16 @@ def test_membership(self): prod2 = Production(var_s, [var_useless]) prod4 = Production(var_b, [ter_b]) prod5 = Production(var_useless, []) - cfg0 = CFG({var_useless, var_s}, {ter_a, ter_b}, var_s, - {prod0, prod1, prod2, prod4, prod5}) + cfg0 = CFG( + {var_useless, var_s}, + {ter_a, ter_b}, + var_s, + {prod0, prod1, prod2, prod4, prod5}, + ) assert cfg0.contains([Epsilon()]) assert cfg0.contains([ter_a, ter_b]) assert cfg0.contains([ter_a, ter_a, ter_b, ter_b]) - assert cfg0.contains( - [ter_a, ter_a, ter_a, ter_b, ter_b, ter_b]) + assert cfg0.contains([ter_a, ter_a, ter_a, ter_b, ter_b, ter_b]) assert not cfg0.contains([ter_a, ter_b, ter_b]) assert not cfg0.contains([ter_a, ter_b, ter_c, ter_b]) assert not cfg0.contains([ter_a, ter_a, ter_a, ter_b, ter_b]) @@ -376,19 +428,20 @@ def test_membership(self): prod7 = Production(var_a, [var_a, var_b]) prod8 = Production(var_a, [ter_a]) prod9 = Production(var_b, [ter_b]) - cfg1 = CFG({var_a, var_b, var_s}, - {ter_a, ter_b}, - var_s, - {prod6, prod7, prod8, prod9}) + cfg1 = CFG( + {var_a, var_b, var_s}, + {ter_a, ter_b}, + var_s, + {prod6, prod7, prod8, prod9}, + ) assert cfg1.contains([ter_a, ter_b, ter_b]) - cfg1 = CFG({"A", "B", "S"}, - {"a", "b"}, - "S", - {prod6, prod7, prod8, prod9}) + cfg1 = CFG( + {"A", "B", "S"}, {"a", "b"}, "S", {prod6, prod7, prod8, prod9} + ) assert cfg1.contains(["a", "b", "b"]) - def test_to_pda(self): - """ Tests the conversion to PDA """ + def test_to_pda(self) -> None: + """Tests the conversion to PDA.""" var_e = Variable("E") var_i = Variable("I") ter_a = Terminal("a") @@ -399,22 +452,34 @@ def test_to_pda(self): ter_par_close = Terminal(")") ter_mult = Terminal("*") ter_plus = Terminal("+") - productions = {Production(var_e, [var_i]), - Production(var_e, [var_e, ter_plus, var_e]), - Production(var_e, [var_e, ter_mult, var_e]), - Production(var_e, [ter_par_open, var_e, ter_par_close]), - Production(var_i, [ter_a]), - Production(var_i, [ter_b]), - Production(var_i, [var_i, ter_a]), - Production(var_i, [var_i, ter_b]), - Production(var_i, [var_i, ter_0]), - Production(var_i, [var_i, ter_1]), - Production(var_i, [var_i, Epsilon()])} - cfg = CFG({var_e, var_i}, - {ter_a, ter_b, ter_0, ter_1, ter_par_open, - ter_par_close, ter_mult, ter_plus}, - var_e, - productions) + productions = { + Production(var_e, [var_i]), + Production(var_e, [var_e, ter_plus, var_e]), + Production(var_e, [var_e, ter_mult, var_e]), + Production(var_e, [ter_par_open, var_e, ter_par_close]), + Production(var_i, [ter_a]), + Production(var_i, [ter_b]), + Production(var_i, [var_i, ter_a]), + Production(var_i, [var_i, ter_b]), + Production(var_i, [var_i, ter_0]), + Production(var_i, [var_i, ter_1]), + Production(var_i, [var_i, Epsilon()]), + } + cfg = CFG( + {var_e, var_i}, + { + ter_a, + ter_b, + ter_0, + ter_1, + ter_par_open, + ter_par_close, + ter_mult, + ter_plus, + }, + var_e, + productions, + ) pda_equivalent = PDA.from_cfg(cfg) assert len(pda_equivalent.states) == 1 assert len(pda_equivalent.final_states) == 0 @@ -422,14 +487,16 @@ def test_to_pda(self): assert len(pda_equivalent.stack_symbols) == 10 assert pda_equivalent.get_number_transitions() == 19 - def test_conversions(self): - """ Tests multiple conversions """ + def test_conversions(self) -> None: + """Tests multiple conversions.""" ter_a = Terminal("a") ter_b = Terminal("b") ter_c = Terminal("c") var_s = Variable("S") - productions = {Production(var_s, [ter_a, var_s, ter_b]), - Production(var_s, [ter_c])} + productions = { + Production(var_s, [ter_a, var_s, ter_b]), + Production(var_s, [ter_c]), + } cfg = CFG(productions=productions, start_symbol=var_s) cfg = PDA.from_cfg(cfg).to_final_state().to_empty_stack().to_cfg() assert cfg.contains([ter_c]) @@ -439,26 +506,30 @@ def test_conversions(self): assert not cfg.contains([ter_b, ter_b, ter_c, ter_a, ter_a]) @staticmethod - def test_profiling_conversions(): - """ Tests multiple conversions """ + def test_profiling_conversions() -> None: + """Tests multiple conversions.""" ter_a = Terminal("a") ter_b = Terminal("b") ter_c = Terminal("c") var_s = Variable("S") - productions = {Production(var_s, [ter_a, var_s, ter_b]), - Production(var_s, [ter_c])} + productions = { + Production(var_s, [ter_a, var_s, ter_b]), + Production(var_s, [ter_c]), + } cfg = CFG(productions=productions, start_symbol=var_s) cfg = PDA.from_cfg(cfg).to_final_state().to_empty_stack().to_cfg() cfg = PDA.from_cfg(cfg).to_final_state().to_empty_stack().to_cfg() PDA.from_cfg(cfg).to_final_state().to_empty_stack().to_cfg() - def test_generation_words(self): - """ Tests the generation of word """ + def test_generation_words(self) -> None: + """Tests the generation of word.""" ter_a = Terminal("a") ter_b = Terminal("b") var_s = Variable("S") - productions = {Production(var_s, [ter_a, var_s, ter_b]), - Production(var_s, [])} + productions = { + Production(var_s, [ter_a, var_s, ter_b]), + Production(var_s, []), + } cfg = CFG(productions=productions, start_symbol=var_s) words0 = list(cfg.get_words(max_length=0)) assert [] in words0 @@ -479,17 +550,19 @@ def test_generation_words(self): assert [ter_a, ter_a, ter_b, ter_b] in words4 assert len(words4) == 3 - def test_generation_words2(self): - """ Tests the generation of word """ + def test_generation_words2(self) -> None: + """Tests the generation of word.""" ter_a = Terminal("a") var_s = Variable("S") var_s1 = Variable("S1") var_s2 = Variable("S2") - productions = {Production(var_s, [var_s1, ter_a]), - Production(var_s1, [var_s2, ter_a]), - Production(var_s1, []), - Production(var_s2, []), - Production(var_s, [])} + productions = { + Production(var_s, [var_s1, ter_a]), + Production(var_s1, [var_s2, ter_a]), + Production(var_s1, []), + Production(var_s2, []), + Production(var_s, []), + } cfg = CFG(productions=productions, start_symbol=var_s) words0 = list(cfg.get_words()) assert [] in words0 @@ -497,24 +570,26 @@ def test_generation_words2(self): assert [ter_a, ter_a] in words0 assert len(words0) == 3 - def test_finite(self): - """ Tests whether a grammar is finite or not """ + def test_finite(self) -> None: + """Tests whether a grammar is finite or not.""" ter_a = Terminal("a") ter_b = Terminal("b") var_s = Variable("S") var_a = Variable("A") var_b = Variable("B") - prod0 = {Production(var_s, [var_a, var_b]), - Production(var_a, [ter_a]), - Production(var_b, [ter_b])} + prod0 = { + Production(var_s, [var_a, var_b]), + Production(var_a, [ter_a]), + Production(var_b, [ter_b]), + } cfg = CFG(productions=prod0, start_symbol=var_s) assert cfg.is_finite() prod0.add(Production(var_a, [var_s])) cfg = CFG(productions=prod0, start_symbol=var_s) assert not cfg.is_finite() - def test_intersection(self): - """ Tests the intersection with a regex """ + def test_intersection(self) -> None: + """Tests the intersection with a regex.""" regex = Regex("a*b*") enfa = regex.to_epsilon_nfa() dfa = DeterministicFiniteAutomaton.from_epsilon_nfa(enfa) @@ -525,9 +600,11 @@ def test_intersection(self): ter_a = Terminal("a") ter_b = Terminal("b") var_s = Variable("S") - productions = {Production(var_s, [ter_a, var_s, ter_b]), - Production(var_s, [ter_b, var_s, ter_a]), - Production(var_s, [])} + productions = { + Production(var_s, [ter_a, var_s, ter_b]), + Production(var_s, [ter_b, var_s, ter_a]), + Production(var_s, []), + } cfg = CFG(productions=productions, start_symbol=var_s) assert cfg.contains([ter_a, ter_a, ter_b, ter_b]) assert not cfg.contains([ter_a, ter_a, ter_b]) @@ -540,27 +617,31 @@ def test_intersection(self): assert not cfg_i.contains([ter_a, ter_a, ter_b]) assert cfg_i.contains([]) - def test_intersection_empty(self): + def test_intersection_empty(self) -> None: regex = Regex("") ter_a = Terminal("a") ter_b = Terminal("b") var_s = Variable("S") - productions = {Production(var_s, [ter_a, var_s, ter_b]), - Production(var_s, [ter_b, var_s, ter_a]), - Production(var_s, [])} + productions = { + Production(var_s, [ter_a, var_s, ter_b]), + Production(var_s, [ter_b, var_s, ter_a]), + Production(var_s, []), + } cfg = CFG(productions=productions, start_symbol=var_s) cfg_i = cfg & regex.to_minimal_dfa() assert not cfg_i - def test_intersection_dfa(self): + def test_intersection_dfa(self) -> None: state0 = State(0) state1 = State(1) symb_a = Symbol("a") symb_b = Symbol("b") - dfa = DeterministicFiniteAutomaton({state0, state1}, - {symb_a, symb_b}, - start_state=state0, - final_states={state0, state1}) + dfa = DeterministicFiniteAutomaton( + {state0, state1}, + {symb_a, symb_b}, + start_state=state0, + final_states={state0, state1}, + ) dfa.add_transition(state0, symb_a, state0) dfa.add_transition(state0, symb_b, state1) dfa.add_transition(state1, symb_b, state1) @@ -570,9 +651,11 @@ def test_intersection_dfa(self): ter_a = Terminal("a") ter_b = Terminal("b") var_s = Variable("S") - productions = {Production(var_s, [ter_a, var_s, ter_b]), - Production(var_s, [ter_b, var_s, ter_a]), - Production(var_s, [])} + productions = { + Production(var_s, [ter_a, var_s, ter_b]), + Production(var_s, [ter_b, var_s, ter_a]), + Production(var_s, []), + } cfg = CFG(productions=productions, start_symbol=var_s) assert cfg.contains([ter_a, ter_a, ter_b, ter_b]) assert not cfg.contains([ter_a, ter_a, ter_b]) @@ -581,14 +664,16 @@ def test_intersection_dfa(self): assert not cfg_i.contains([ter_a, ter_a, ter_b]) assert cfg_i.contains([]) - def test_intersection_with_epsilon(self): + def test_intersection_with_epsilon(self) -> None: state0 = State(0) state1 = State(1) symb_a = Symbol("a") - dfa = DeterministicFiniteAutomaton({state0, state1}, - {symb_a}, - start_state=state0, - final_states={state1}) + dfa = DeterministicFiniteAutomaton( + {state0, state1}, + {symb_a}, + start_state=state0, + final_states={state1}, + ) dfa.add_transition(state0, symb_a, state1) assert dfa.accepts([symb_a]) @@ -596,10 +681,12 @@ def test_intersection_with_epsilon(self): var_s = Variable("S") var_l = Variable("L") var_t = Variable("T") - productions = {Production(var_s, [var_l, var_t]), - Production(var_l, [Epsilon()]), - Production(var_t, [ter_a]), - Production(var_t, [Epsilon()])} + productions = { + Production(var_s, [var_l, var_t]), + Production(var_l, [Epsilon()]), + Production(var_t, [ter_a]), + Production(var_t, [Epsilon()]), + } cfg = CFG(productions=productions, start_symbol=var_s) assert not cfg.is_empty() assert cfg.contains([ter_a]) @@ -615,14 +702,16 @@ def test_intersection_with_epsilon(self): cfg_i = cfg.intersection(dfa) assert not cfg_i.is_empty() - def test_intersection_dfa2(self): + def test_intersection_dfa2(self) -> None: state0 = State(0) symb_a = Symbol("a") symb_b = Symbol("b") - dfa = DeterministicFiniteAutomaton({state0}, - {symb_a, symb_b}, - start_state=state0, - final_states={state0}) + dfa = DeterministicFiniteAutomaton( + {state0}, + {symb_a, symb_b}, + start_state=state0, + final_states={state0}, + ) dfa.add_transition(state0, symb_a, state0) dfa.add_transition(state0, symb_b, state0) assert dfa.accepts([symb_a, symb_a, symb_b, symb_b]) @@ -632,11 +721,13 @@ def test_intersection_dfa2(self): var_s = Variable("S") var_s1 = Variable("S1") var_l = Variable("L") - productions = {Production(var_s, [var_l, var_s1]), - Production(var_l, [Epsilon()]), - Production(var_s1, [ter_a, var_s1, ter_b]), - Production(var_s1, [ter_b, var_s1, ter_a]), - Production(var_s1, [])} + productions = { + Production(var_s, [var_l, var_s1]), + Production(var_l, [Epsilon()]), + Production(var_s1, [ter_a, var_s1, ter_b]), + Production(var_s1, [ter_b, var_s1, ter_a]), + Production(var_s1, []), + } cfg = CFG(productions=productions, start_symbol=var_s) assert cfg.contains([ter_a, ter_a, ter_b, ter_b]) assert not cfg.contains([ter_a, ter_a, ter_b]) @@ -645,15 +736,17 @@ def test_intersection_dfa2(self): assert cfg_i.contains([ter_a, ter_a, ter_b, ter_b]) assert cfg_i.contains([]) - def test_profiling_intersection(self): + def test_profiling_intersection(self) -> None: size = 3 states = [State(i) for i in range(size * 2 + 1)] symb_a = Symbol("a") symb_b = Symbol("b") - dfa = DeterministicFiniteAutomaton(set(states), - {symb_a, symb_b}, - start_state=states[0], - final_states={states[-1]}) + dfa = DeterministicFiniteAutomaton( + set(states), + {symb_a, symb_b}, + start_state=states[0], + final_states={states[-1]}, + ) for i in range(size): dfa.add_transition(states[i], symb_a, states[i + 1]) for i in range(size, size * 2): @@ -664,70 +757,76 @@ def test_profiling_intersection(self): var_s = Variable("S") var_s1 = Variable("S1") var_l = Variable("L") - productions = [Production(var_s, [var_l, var_s1]), - Production(var_l, [Epsilon()]), - Production(var_s1, [ter_a, var_s1, ter_b]), - Production(var_s1, [ter_b, var_s1, ter_a]), - Production(var_s1, [])] + productions = [ + Production(var_s, [var_l, var_s1]), + Production(var_l, [Epsilon()]), + Production(var_s1, [ter_a, var_s1, ter_b]), + Production(var_s1, [ter_b, var_s1, ter_a]), + Production(var_s1, []), + ] cfg = CFG(productions=productions, start_symbol=var_s) cfg_i = cfg.intersection(dfa) assert not cfg_i.is_empty() assert cfg_i.contains([ter_a] * size + [ter_b] * size) assert not cfg_i.contains([]) - def test_string_variable(self): + def test_string_variable(self) -> None: var = Variable("A") assert repr(var) == "Variable(A)" - def test_get_leftmost_derivation(self): + def test_get_leftmost_derivation(self) -> None: ter_a = Terminal("a") ter_b = Terminal("b") var_s = Variable("S") var_a = Variable("A") var_b = Variable("B") var_c = Variable("C") - productions = [Production(var_s, [var_c, var_b]), - Production(var_c, [var_a, var_a]), - Production(var_a, [ter_a]), - Production(var_b, [ter_b]) - ] + productions = [ + Production(var_s, [var_c, var_b]), + Production(var_c, [var_a, var_a]), + Production(var_a, [ter_a]), + Production(var_b, [ter_b]), + ] cfg = CFG(productions=productions, start_symbol=var_s) parse_tree = cfg.get_cnf_parse_tree([ter_a, ter_a, ter_b]) derivation = parse_tree.get_leftmost_derivation() - assert derivation == \ - [[var_s], - [var_c, var_b], - [var_a, var_a, var_b], - [ter_a, var_a, var_b], - [ter_a, ter_a, var_b], - [ter_a, ter_a, ter_b]] + assert derivation == [ + [var_s], + [var_c, var_b], + [var_a, var_a, var_b], + [ter_a, var_a, var_b], + [ter_a, ter_a, var_b], + [ter_a, ter_a, ter_b], + ] with pytest.raises(DerivationDoesNotExistError): cfg.get_cnf_parse_tree([]) - def test_get_rightmost_derivation(self): + def test_get_rightmost_derivation(self) -> None: ter_a = Terminal("a") ter_b = Terminal("b") var_s = Variable("S") var_a = Variable("A") var_b = Variable("B") var_c = Variable("C") - productions = [Production(var_s, [var_c, var_b]), - Production(var_c, [var_a, var_a]), - Production(var_a, [ter_a]), - Production(var_b, [ter_b]) - ] + productions = [ + Production(var_s, [var_c, var_b]), + Production(var_c, [var_a, var_a]), + Production(var_a, [ter_a]), + Production(var_b, [ter_b]), + ] cfg = CFG(productions=productions, start_symbol=var_s) parse_tree = cfg.get_cnf_parse_tree([ter_a, ter_a, ter_b]) derivation = parse_tree.get_rightmost_derivation() - assert derivation == \ - [[var_s], - [var_c, var_b], - [var_c, ter_b], - [var_a, var_a, ter_b], - [var_a, ter_a, ter_b], - [ter_a, ter_a, ter_b]] - - def test_derivation_does_not_exist(self): + assert derivation == [ + [var_s], + [var_c, var_b], + [var_c, ter_b], + [var_a, var_a, ter_b], + [var_a, ter_a, ter_b], + [ter_a, ter_a, ter_b], + ] + + def test_derivation_does_not_exist(self) -> None: var_s = Variable("S") ter_a = Terminal("a") ter_b = Terminal("b") @@ -736,7 +835,7 @@ def test_derivation_does_not_exist(self): parse_tree = cfg.get_cnf_parse_tree([ter_a, ter_b]) parse_tree.get_rightmost_derivation() - def test_derivation_empty(self): + def test_derivation_empty(self) -> None: var_s = Variable("S") productions = [Production(var_s, [Epsilon()])] cfg = CFG(productions=productions, start_symbol=var_s) @@ -744,7 +843,7 @@ def test_derivation_empty(self): derivation = parse_tree.get_rightmost_derivation() assert [[var_s], []] == derivation - def test_from_text(self): + def test_from_text(self) -> None: text = """ S -> A B A -> Bobo r @@ -755,7 +854,7 @@ def test_from_text(self): assert len(cfg.terminals) == 1 assert cfg.start_symbol == Variable("S") - def test_from_text2(self): + def test_from_text2(self) -> None: text = """ S -> A B\n\rA -> a B -> b\r @@ -764,59 +863,60 @@ def test_from_text2(self): assert cfg.contains(["a", "b"]) assert ["a", "b"] in cfg - def test_from_text_union(self): + def test_from_text_union(self) -> None: text = """ "VAR:S" -> TER:a | b """ cfg = CFG.from_text(text) assert 2 == len(cfg.productions) - def test_epsilon(self): + def test_epsilon(self) -> None: text = "S -> epsilon" cfg = CFG.from_text(text) assert cfg.generate_epsilon() assert len(cfg.terminals) == 0 - def test_epsilon2(self): + def test_epsilon2(self) -> None: text = "S ->$" cfg = CFG.from_text(text) assert cfg.generate_epsilon() - def test_generate_epsilon(self): + def test_generate_epsilon(self) -> None: var_s = Variable("S") ter_a = Terminal("a") productions = [Production(var_s, [ter_a])] cfg = CFG(productions=productions, start_symbol=var_s) assert not cfg.generate_epsilon() - def test_change_starting_variable(self): + def test_change_starting_variable(self) -> None: text = """S1 -> a""" cfg = CFG.from_text(text, start_symbol="S1") assert Variable("S1") == cfg.start_symbol - def test_is_not_normal_form(self): + def test_is_not_normal_form(self) -> None: text = get_example_text_duplicate() cfg = CFG.from_text(text, start_symbol="E") assert not cfg.is_normal_form() - def test_is_normal_form(self): + def test_is_normal_form(self) -> None: text = """ - E -> T E’ - E’ -> T E’ - T -> F T’ - T’ -> * - F -> ( | id - """ + E -> T E’ + E’ -> T E’ + T -> F T’ + T’ -> * + F -> ( | id + """ cfg = CFG.from_text(text, start_symbol="E") assert cfg.is_normal_form() - def test_to_text(self): - text = """E -> T E’ + def test_to_text(self) -> None: + text = """ + E -> T E’ E’ -> T E’ T -> F T’ T’ -> * F -> ( | id - """ + """ text_result = CFG.from_text(text, start_symbol="E").to_text() assert "E -> T E’" in text_result assert "E’ -> T E’" in text_result @@ -825,7 +925,7 @@ def test_to_text(self): assert "F -> (" in text_result assert "F -> id" in text_result - def test_to_text_cnf(self): + def test_to_text_cnf(self) -> None: cfg = CFG.from_text("S -> a S b | a b") cnf = cfg.to_normal_form() assert cnf.contains(["a", "b"]) @@ -833,11 +933,11 @@ def test_to_text_cnf(self): new_cfg = CFG.from_text(new_text) assert new_cfg.contains(["a", "b"]) - def test_to_text_epsilon(self): + def test_to_text_epsilon(self) -> None: cfg = CFG.from_text("S -> a S b | a b epsilon") assert cfg.contains(["a", "b"]) - def test_copy(self): + def test_copy(self) -> None: text_example = get_example_text_duplicate() cfg = CFG.from_text(text_example) cfg_copy = cfg.copy() @@ -847,12 +947,13 @@ def test_copy(self): assert cfg.start_symbol == cfg_copy.start_symbol assert cfg is not cfg_copy - def test_add_production(self): + def test_add_production(self) -> None: text_example = get_example_text_duplicate() cfg = CFG.from_text(text_example) assert Epsilon() not in cfg.terminals - production = Production(Variable("K"), - [Epsilon(), Terminal("a"), Variable("B")]) + production = Production( + Variable("K"), [Epsilon(), Terminal("a"), Variable("B")] + ) cfg.add_production(production) assert production in cfg.productions assert "K" in cfg.variables @@ -860,7 +961,7 @@ def test_add_production(self): assert "B" in cfg.variables assert Epsilon() not in cfg.terminals - def test_start_symbol(self): + def test_start_symbol(self) -> None: cfg = CFG() assert not cfg.variables assert not cfg.start_symbol @@ -873,17 +974,17 @@ def test_start_symbol(self): assert not cfg.start_symbol -def get_example_text_duplicate(): - """ Duplicate text """ +def get_example_text_duplicate() -> str: + """Duplicate text.""" text = """ - E -> T E’ - E’ -> + T E’ | Є - T -> F T’ - T’ -> * F T’ | Є - F -> ( E ) | id - """ + E -> T E’ + E’ -> + T E’ | Є + T -> F T’ + T’ -> * F T’ | Є + F -> ( E ) | id + """ return text -if __name__ == '__main__': +if __name__ == "__main__": pytest.main() diff --git a/pyformlang/cfg/tests/test_llone_parser.py b/pyformlang/cfg/tests/test_llone_parser.py index e7bb2fa..fa3db46 100644 --- a/pyformlang/cfg/tests/test_llone_parser.py +++ b/pyformlang/cfg/tests/test_llone_parser.py @@ -1,6 +1,4 @@ -""" -Test for LL(1) parser -""" +"""Test for LL(1) parser.""" from os import path @@ -13,29 +11,24 @@ class TestLLOneParser: - """ Tests the LL(1) Parser """ + """Tests the LL(1) Parser.""" # pylint: disable=missing-function-docstring, too-many-public-methods - def test_get_first_set(self): + def test_get_first_set(self) -> None: # Example from: # https://www.geeksforgeeks.org/first-set-in-syntax-analysis/ text = get_example_text_duplicate() cfg = CFG.from_text(text) llone_parser = LLOneParser(cfg) first_set = llone_parser.get_first_set() - assert first_set[Variable("E")] == \ - {Terminal("("), Terminal("id")} - assert first_set[Variable("E’")] == \ - {Terminal("+"), Epsilon()} - assert first_set[Variable("T")] == \ - {Terminal("("), Terminal("id")} - assert first_set[Variable("T’")] == \ - {Terminal("*"), Epsilon()} - assert first_set[Variable("F")] == \ - {Terminal("("), Terminal("id")} + assert first_set[Variable("E")] == {Terminal("("), Terminal("id")} + assert first_set[Variable("E’")] == {Terminal("+"), Epsilon()} + assert first_set[Variable("T")] == {Terminal("("), Terminal("id")} + assert first_set[Variable("T’")] == {Terminal("*"), Epsilon()} + assert first_set[Variable("F")] == {Terminal("("), Terminal("id")} - def test_get_first_set2(self): + def test_get_first_set2(self) -> None: # Example from: # https://www.geeksforgeeks.org/first-set-in-syntax-analysis/ text = """ @@ -47,36 +40,38 @@ def test_get_first_set2(self): cfg = CFG.from_text(text) llone_parser = LLOneParser(cfg) first_set = llone_parser.get_first_set() - assert first_set[Variable("S")] == \ - {Terminal(x) for x in ("d", "g", "h", "b", - "a")}.union({Epsilon()}) - assert first_set[Variable("A")] == \ - {Terminal(x) for x in ("d", "g", - "h")}.union({Epsilon()}) - assert first_set[Variable("B")] == \ - {Terminal(x) for x in ["g"]}.union({Epsilon()}) - assert first_set[Variable("C")] == \ - {Terminal(x) for x in ["h"]}.union({Epsilon()}) + assert first_set[Variable("S")] == { + Terminal(x) for x in ("d", "g", "h", "b", "a") + }.union({Epsilon()}) + assert first_set[Variable("A")] == { + Terminal(x) for x in ("d", "g", "h") + }.union({Epsilon()}) + assert first_set[Variable("B")] == {Terminal(x) for x in ["g"]}.union( + {Epsilon()} + ) + assert first_set[Variable("C")] == {Terminal(x) for x in ["h"]}.union( + {Epsilon()} + ) - def test_get_follow_set(self): + def test_get_follow_set(self) -> None: # Example from: # https://www.geeksforgeeks.org/follow-set-in-syntax-analysis/ text = get_example_text_duplicate() cfg = CFG.from_text(text, start_symbol="E") llone_parser = LLOneParser(cfg) follow_set = llone_parser.get_follow_set() - assert follow_set[Variable("E")] == \ - {"$", Terminal(")")} - assert follow_set[Variable("E’")] == \ - {"$", Terminal(")")} - assert follow_set[Variable("T")] == \ - {"$", Terminal("+"), Terminal(")")} - assert follow_set[Variable("T’")] == \ - {"$", Terminal("+"), Terminal(")")} - assert follow_set[Variable("F")] == \ - {"$", Terminal("+"), Terminal("*"), Terminal(")")} + assert follow_set[Variable("E")] == {"$", Terminal(")")} + assert follow_set[Variable("E’")] == {"$", Terminal(")")} + assert follow_set[Variable("T")] == {"$", Terminal("+"), Terminal(")")} + assert follow_set[Variable("T’")] == {"$", Terminal("+"), Terminal(")")} + assert follow_set[Variable("F")] == { + "$", + Terminal("+"), + Terminal("*"), + Terminal(")"), + } - def test_get_follow_set2(self): + def test_get_follow_set2(self) -> None: # Example from: # https://www.geeksforgeeks.org/follow-set-in-syntax-analysis/ text = """ @@ -88,39 +83,50 @@ def test_get_follow_set2(self): cfg = CFG.from_text(text) llone_parser = LLOneParser(cfg) follow_set = llone_parser.get_follow_set() - assert follow_set[Variable("S")] == \ - {"$"} - assert follow_set[Variable("A")] == \ - {"$", Terminal("h"), Terminal("g")} - assert follow_set[Variable("B")] == \ - {"$", Terminal("h"), Terminal("g"), Terminal("a")} - assert follow_set[Variable("C")] == \ - {"$", Terminal("h"), Terminal("g"), Terminal("b")} + assert follow_set[Variable("S")] == {"$"} + assert follow_set[Variable("A")] == {"$", Terminal("h"), Terminal("g")} + assert follow_set[Variable("B")] == { + "$", + Terminal("h"), + Terminal("g"), + Terminal("a"), + } + assert follow_set[Variable("C")] == { + "$", + Terminal("h"), + Terminal("g"), + Terminal("b"), + } - def test_get_llone_table(self): + def test_get_llone_table(self) -> None: # Example from: # https://www.geeksforgeeks.org/construction-of-ll1-parsing-table/ text = get_example_text_duplicate() cfg = CFG.from_text(text, start_symbol="E") llone_parser = LLOneParser(cfg) parsing_table = llone_parser.get_llone_parsing_table() - assert len(parsing_table.get(Variable("E"), {}) - .get(Terminal("id"), [])) == \ - 1 - assert len(parsing_table.get(Variable("E"), {}) - .get(Terminal("+"), [])) == \ - 0 - assert len(parsing_table.get(Variable("T’"), {}) - .get(Terminal(")"), [])) == \ - 1 - assert len(parsing_table.get(Variable("F"), {}) - .get(Terminal("("), [])) == \ - 1 - assert len(parsing_table.get(Variable("F"), {}) - .get(Terminal("id"), [])) == \ - 1 + assert ( + len(parsing_table.get(Variable("E"), {}).get(Terminal("id"), [])) + == 1 + ) + assert ( + len(parsing_table.get(Variable("E"), {}).get(Terminal("+"), [])) + == 0 + ) + assert ( + len(parsing_table.get(Variable("T’"), {}).get(Terminal(")"), [])) + == 1 + ) + assert ( + len(parsing_table.get(Variable("F"), {}).get(Terminal("("), [])) + == 1 + ) + assert ( + len(parsing_table.get(Variable("F"), {}).get(Terminal("id"), [])) + == 1 + ) - def test_llone_table_non_llone(self): + def test_llone_table_non_llone(self) -> None: text = """ S -> A | a A -> a @@ -128,20 +134,24 @@ def test_llone_table_non_llone(self): cfg = CFG.from_text(text, start_symbol="E") llone_parser = LLOneParser(cfg) parsing_table = llone_parser.get_llone_parsing_table() - assert len(parsing_table.get(Variable("S"), {}) - .get(Terminal("a"), [])) == \ - 2 - assert len(parsing_table.get(Variable("A"), {}) - .get(Terminal("a"), [])) == \ - 1 - assert len(parsing_table.get(Variable("S"), {}) - .get(Terminal("$"), [])) == \ - 0 - assert len(parsing_table.get(Variable("A"), {}) - .get(Terminal("$"), [])) == \ - 0 + assert ( + len(parsing_table.get(Variable("S"), {}).get(Terminal("a"), [])) + == 2 + ) + assert ( + len(parsing_table.get(Variable("A"), {}).get(Terminal("a"), [])) + == 1 + ) + assert ( + len(parsing_table.get(Variable("S"), {}).get(Terminal("$"), [])) + == 0 + ) + assert ( + len(parsing_table.get(Variable("A"), {}).get(Terminal("$"), [])) + == 0 + ) - def test_is_llone_parsable(self): + def test_is_llone_parsable(self) -> None: # Example from: # https://www.geeksforgeeks.org/construction-of-ll1-parsing-table/ text = get_example_text_duplicate() @@ -149,7 +159,7 @@ def test_is_llone_parsable(self): llone_parser = LLOneParser(cfg) assert llone_parser.is_llone_parsable() - def test_is_not_llone_parsable(self): + def test_is_not_llone_parsable(self) -> None: # Example from: # https://www.geeksforgeeks.org/construction-of-ll1-parsing-table/ text = """ @@ -160,86 +170,162 @@ def test_is_not_llone_parsable(self): llone_parser = LLOneParser(cfg) assert not llone_parser.is_llone_parsable() - def test_get_llone_parse_tree(self): + def test_get_llone_parse_tree(self) -> None: text = get_example_text_duplicate() cfg = CFG.from_text(text, start_symbol="E") llone_parser = LLOneParser(cfg) - parse_tree = llone_parser.get_llone_parse_tree(["id", "+", "id", - "*", "id"]) + parse_tree = llone_parser.get_llone_parse_tree( + ["id", "+", "id", "*", "id"] + ) assert parse_tree.value == Variable("E") assert len(parse_tree.sons) == 2 - def test_get_llone_leftmost_derivation(self): + def test_get_llone_leftmost_derivation(self) -> None: text = get_example_text_duplicate() cfg = CFG.from_text(text, start_symbol="E") llone_parser = LLOneParser(cfg) - parse_tree = llone_parser.get_llone_parse_tree(["id", "+", "id", - "*", "id"]) - assert parse_tree.get_leftmost_derivation() == \ - [[Variable("E")], - [Variable("T"), Variable("E’")], - [Variable("F"), Variable("T’"), Variable("E’")], - [Terminal("id"), Variable("T’"), Variable("E’")], - [Terminal("id"), Variable("E’")], - [Terminal("id"), Terminal("+"), Variable("T"), Variable("E’")], - [Terminal("id"), Terminal("+"), Variable("F"), Variable("T’"), - Variable("E’")], - [Terminal("id"), Terminal("+"), Terminal("id"), Variable("T’"), - Variable("E’")], - [Terminal("id"), Terminal("+"), Terminal("id"), Terminal("*"), - Variable("F"), Variable("T’"), Variable("E’")], - [Terminal("id"), Terminal("+"), Terminal("id"), Terminal("*"), - Terminal("id"), Variable("T’"), Variable("E’")], - [Terminal("id"), Terminal("+"), Terminal("id"), Terminal("*"), - Terminal("id"), Variable("E’")], - [Terminal("id"), Terminal("+"), Terminal("id"), Terminal("*"), - Terminal("id")] - ] + parse_tree = llone_parser.get_llone_parse_tree( + ["id", "+", "id", "*", "id"] + ) + assert parse_tree.get_leftmost_derivation() == [ + [Variable("E")], + [Variable("T"), Variable("E’")], + [Variable("F"), Variable("T’"), Variable("E’")], + [Terminal("id"), Variable("T’"), Variable("E’")], + [Terminal("id"), Variable("E’")], + [Terminal("id"), Terminal("+"), Variable("T"), Variable("E’")], + [ + Terminal("id"), + Terminal("+"), + Variable("F"), + Variable("T’"), + Variable("E’"), + ], + [ + Terminal("id"), + Terminal("+"), + Terminal("id"), + Variable("T’"), + Variable("E’"), + ], + [ + Terminal("id"), + Terminal("+"), + Terminal("id"), + Terminal("*"), + Variable("F"), + Variable("T’"), + Variable("E’"), + ], + [ + Terminal("id"), + Terminal("+"), + Terminal("id"), + Terminal("*"), + Terminal("id"), + Variable("T’"), + Variable("E’"), + ], + [ + Terminal("id"), + Terminal("+"), + Terminal("id"), + Terminal("*"), + Terminal("id"), + Variable("E’"), + ], + [ + Terminal("id"), + Terminal("+"), + Terminal("id"), + Terminal("*"), + Terminal("id"), + ], + ] - def test_get_llone_rightmost_derivation(self): + def test_get_llone_rightmost_derivation(self) -> None: text = get_example_text_duplicate() cfg = CFG.from_text(text, start_symbol="E") llone_parser = LLOneParser(cfg) - parse_tree = llone_parser.get_llone_parse_tree(["id", "+", "id", - "*", "id"]) - assert parse_tree.get_rightmost_derivation() == \ - [[Variable("E")], - [Variable("T"), Variable("E’")], - [Variable("T"), Terminal("+"), Variable("T"), Variable("E’")], - [Variable("T"), Terminal("+"), Variable("T")], - [Variable("T"), Terminal("+"), Variable("F"), Variable("T’")], - [Variable("T"), Terminal("+"), Variable("F"), Terminal("*"), - Variable("F"), Variable("T’")], - [Variable("T"), Terminal("+"), Variable("F"), Terminal("*"), - Variable("F")], - [Variable("T"), Terminal("+"), Variable("F"), Terminal("*"), - Terminal("id")], - [Variable("T"), Terminal("+"), Terminal("id"), Terminal("*"), - Terminal("id")], - [Variable("F"), Variable("T’"), Terminal("+"), Terminal("id"), - Terminal("*"), Terminal("id")], - [Variable("F"), Terminal("+"), Terminal("id"), - Terminal("*"), Terminal("id")], - [Terminal("id"), Terminal("+"), Terminal("id"), - Terminal("*"), Terminal("id")], - ] + parse_tree = llone_parser.get_llone_parse_tree( + ["id", "+", "id", "*", "id"] + ) + assert parse_tree.get_rightmost_derivation() == [ + [Variable("E")], + [Variable("T"), Variable("E’")], + [Variable("T"), Terminal("+"), Variable("T"), Variable("E’")], + [Variable("T"), Terminal("+"), Variable("T")], + [Variable("T"), Terminal("+"), Variable("F"), Variable("T’")], + [ + Variable("T"), + Terminal("+"), + Variable("F"), + Terminal("*"), + Variable("F"), + Variable("T’"), + ], + [ + Variable("T"), + Terminal("+"), + Variable("F"), + Terminal("*"), + Variable("F"), + ], + [ + Variable("T"), + Terminal("+"), + Variable("F"), + Terminal("*"), + Terminal("id"), + ], + [ + Variable("T"), + Terminal("+"), + Terminal("id"), + Terminal("*"), + Terminal("id"), + ], + [ + Variable("F"), + Variable("T’"), + Terminal("+"), + Terminal("id"), + Terminal("*"), + Terminal("id"), + ], + [ + Variable("F"), + Terminal("+"), + Terminal("id"), + Terminal("*"), + Terminal("id"), + ], + [ + Terminal("id"), + Terminal("+"), + Terminal("id"), + Terminal("*"), + Terminal("id"), + ], + ] - def test_save_tree(self): + def test_save_tree(self) -> None: text = """ - E -> T E' - E' -> + T E' | epsilon - T -> F T' - T' -> * F T' | epsilon - F -> ( E ) | id - """ + E -> T E' + E' -> + T E' | epsilon + T -> F T' + T' -> * F T' | epsilon + F -> ( E ) | id + """ cfg = CFG.from_text(text, start_symbol="E") llone_parser = LLOneParser(cfg) - parse_tree = llone_parser.get_llone_parse_tree(["id", "+", "id", - "*", "id"]) + parse_tree = llone_parser.get_llone_parse_tree( + ["id", "+", "id", "*", "id"] + ) parse_tree.write_as_dot("parse_tree.dot") assert path.exists("parse_tree.dot") - def test_sentence_cfg(self): + def test_sentence_cfg(self) -> None: cfg = CFG.from_text(""" S -> NP VP PUNC PUNC -> . | ! @@ -259,26 +345,56 @@ def test_sentence_cfg(self): cnf = cfg.to_normal_form() assert cnf.is_normal_form() llone_parser = LLOneParser(cfg) - parse_tree = llone_parser.get_llone_parse_tree(["georges", "sees", - "a", "gorilla", "."]) - assert parse_tree.get_leftmost_derivation() == \ - [[Variable("S")], - [Variable("NP"), Variable("VP"), Variable("PUNC")], - [Terminal("georges"), Variable("VP"), Variable("PUNC")], - [Terminal("georges"), Variable("V"), Variable("NP"), - Variable("PUNC")], - [Terminal("georges"), Terminal("sees"), - Variable("NP"), Variable("PUNC")], - [Terminal("georges"), Terminal("sees"), Variable("Det"), - Variable("N"), Variable("PUNC")], - [Terminal("georges"), Terminal("sees"), Terminal("a"), - Variable("N"), Variable("PUNC")], - [Terminal("georges"), Terminal("sees"), Terminal("a"), - Terminal("gorilla"), Variable("PUNC")], - [Terminal("georges"), Terminal("sees"), Terminal("a"), - Terminal("gorilla"), Terminal(".")]] + parse_tree = llone_parser.get_llone_parse_tree( + ["georges", "sees", "a", "gorilla", "."] + ) + assert parse_tree.get_leftmost_derivation() == [ + [Variable("S")], + [Variable("NP"), Variable("VP"), Variable("PUNC")], + [Terminal("georges"), Variable("VP"), Variable("PUNC")], + [ + Terminal("georges"), + Variable("V"), + Variable("NP"), + Variable("PUNC"), + ], + [ + Terminal("georges"), + Terminal("sees"), + Variable("NP"), + Variable("PUNC"), + ], + [ + Terminal("georges"), + Terminal("sees"), + Variable("Det"), + Variable("N"), + Variable("PUNC"), + ], + [ + Terminal("georges"), + Terminal("sees"), + Terminal("a"), + Variable("N"), + Variable("PUNC"), + ], + [ + Terminal("georges"), + Terminal("sees"), + Terminal("a"), + Terminal("gorilla"), + Variable("PUNC"), + ], + [ + Terminal("georges"), + Terminal("sees"), + Terminal("a"), + Terminal("gorilla"), + Terminal("."), + ], + ] parse_tree.write_as_dot("parse_tree.dot") -if __name__ == '__main__': +if __name__ == "__main__": pytest.main() diff --git a/pyformlang/cfg/tests/test_production.py b/pyformlang/cfg/tests/test_production.py index f74cff4..18ed9ca 100644 --- a/pyformlang/cfg/tests/test_production.py +++ b/pyformlang/cfg/tests/test_production.py @@ -1,13 +1,14 @@ -""" Tests the productions """ +"""Tests the productions.""" from pyformlang.cfg import Production, Variable, Terminal class TestProduction: - """ Tests the production """ + """Tests the production.""" + # pylint: disable=missing-function-docstring - def test_creation(self): + def test_creation(self) -> None: prod0 = Production(Variable("S0"), [Terminal("S1"), Variable("a")]) prod1 = Production(Variable("S0"), [Terminal("S1"), Variable("a")]) prod2 = Production(Variable("S0'"), [Terminal("S1"), Variable("a")]) diff --git a/pyformlang/cfg/tests/test_recursive_decent_parser.py b/pyformlang/cfg/tests/test_recursive_decent_parser.py index 99ca514..f99823d 100644 --- a/pyformlang/cfg/tests/test_recursive_decent_parser.py +++ b/pyformlang/cfg/tests/test_recursive_decent_parser.py @@ -1,61 +1,106 @@ -# pylint: disable=missing-module-docstring -# pylint: disable=missing-class-docstring -# pylint: disable=missing-function-docstring -from pyformlang.cfg import CFG, Variable, Terminal -from pyformlang.cfg.recursive_decent_parser import \ - RecursiveDecentParser, NotParsableError +"""Tests for recursive top-down parser.""" + import pytest +from pyformlang.cfg import CFG, Variable, Terminal +from pyformlang.cfg.recursive_decent_parser import ( + RecursiveDecentParser, + NotParsableError, +) + @pytest.fixture -def parser(): +def example_parser() -> RecursiveDecentParser: cfg = CFG.from_text(""" E -> S + S E -> S * S S -> ( E ) S -> int """) - yield RecursiveDecentParser(cfg) + return RecursiveDecentParser(cfg) class TestRecursiveDecentParser: + def test_creation(self, + example_parser: RecursiveDecentParser) -> None: + assert example_parser is not None - def test_creation(self, parser): - assert parser is not None - - def test_get_parsing_tree(self, parser): - assert parser.is_parsable( + def test_get_parsing_tree(self, + example_parser: RecursiveDecentParser) -> None: + assert example_parser.is_parsable( + ["(", "int", "+", "(", "int", "*", "int", ")", ")"] + ) + parse_tree = example_parser.get_parse_tree( ["(", "int", "+", "(", "int", "*", "int", ")", ")"] ) - parse_tree = parser.get_parse_tree( - ["(", "int", "+", "(", "int", "*", "int", ")", ")"]) derivation = parse_tree.get_leftmost_derivation() - assert derivation == \ - [[Variable("S")], - [Terminal("("), Variable("E"), Terminal(")")], - [Terminal("("), Variable("S"), Terminal("+"), Variable("S"), - Terminal(")")], - [Terminal("("), Terminal("int"), Terminal("+"), Variable("S"), - Terminal(")")], - [Terminal("("), Terminal("int"), Terminal("+"), Terminal("("), - Variable("E"), Terminal(")"), Terminal(")")], - [Terminal("("), Terminal("int"), Terminal("+"), Terminal("("), - Variable("S"), Terminal("*"), Variable("S"), Terminal(")"), - Terminal(")")], - [Terminal("("), Terminal("int"), Terminal("+"), Terminal("("), - Terminal("int"), Terminal("*"), Variable("S"), Terminal(")"), - Terminal(")")], - [Terminal("("), Terminal("int"), Terminal("+"), Terminal("("), - Terminal("int"), Terminal("*"), Terminal("int"), Terminal(")"), - Terminal(")")], - ] + assert derivation == [ + [Variable("S")], + [Terminal("("), Variable("E"), Terminal(")")], + [ + Terminal("("), + Variable("S"), + Terminal("+"), + Variable("S"), + Terminal(")"), + ], + [ + Terminal("("), + Terminal("int"), + Terminal("+"), + Variable("S"), + Terminal(")"), + ], + [ + Terminal("("), + Terminal("int"), + Terminal("+"), + Terminal("("), + Variable("E"), + Terminal(")"), + Terminal(")"), + ], + [ + Terminal("("), + Terminal("int"), + Terminal("+"), + Terminal("("), + Variable("S"), + Terminal("*"), + Variable("S"), + Terminal(")"), + Terminal(")"), + ], + [ + Terminal("("), + Terminal("int"), + Terminal("+"), + Terminal("("), + Terminal("int"), + Terminal("*"), + Variable("S"), + Terminal(")"), + Terminal(")"), + ], + [ + Terminal("("), + Terminal("int"), + Terminal("+"), + Terminal("("), + Terminal("int"), + Terminal("*"), + Terminal("int"), + Terminal(")"), + Terminal(")"), + ], + ] - def test_no_parse_tree(self, parser): + def test_no_parse_tree(self, example_parser: RecursiveDecentParser) -> None: with pytest.raises(NotParsableError): - parser.get_parse_tree([")"]) - assert not (parser.is_parsable([")"])) + example_parser.get_parse_tree([")"]) + assert not example_parser.is_parsable([")"]) - def test_infinite_recursion(self): + def test_infinite_recursion(self) -> None: cfg = CFG.from_text(""" S -> S E """) diff --git a/pyformlang/cfg/tests/test_terminal.py b/pyformlang/cfg/tests/test_terminal.py index 53fa5a0..20ab569 100644 --- a/pyformlang/cfg/tests/test_terminal.py +++ b/pyformlang/cfg/tests/test_terminal.py @@ -1,13 +1,15 @@ -""" Tests the terminal """ +"""Tests the terminal.""" + from pyformlang.cfg import Variable, Terminal, Epsilon from pyformlang.finite_automaton import State, Symbol, Epsilon as FAEpsilon class TestTerminal: - """ Tests the terminal """ + """Tests the terminal.""" + # pylint: disable=missing-function-docstring - def test_creation(self): + def test_creation(self) -> None: terminal0 = Terminal(0) terminal1 = Terminal(1) terminal2 = Terminal(0) @@ -27,7 +29,7 @@ def test_creation(self): assert str(terminal0) == "0" assert repr(terminal0) == "Terminal(0)" - def test_eq(self): + def test_eq(self) -> None: assert "epsilon" == Epsilon() assert Epsilon() == "ɛ" assert Terminal("A") != Variable("A") diff --git a/pyformlang/cfg/tests/test_variable.py b/pyformlang/cfg/tests/test_variable.py index f3ed904..03072cc 100644 --- a/pyformlang/cfg/tests/test_variable.py +++ b/pyformlang/cfg/tests/test_variable.py @@ -1,12 +1,14 @@ -""" Tests the variable """ +"""Tests the variable.""" + from pyformlang.cfg import Variable class TestVariable: - """ Tests the variable """ + """Tests the variable.""" + # pylint: disable=missing-function-docstring - def test_creation(self): + def test_creation(self) -> None: variable0 = Variable(0) variable1 = Variable(1) variable2 = Variable(0) diff --git a/pyformlang/fcfg/tests/test_fcfg.py b/pyformlang/fcfg/tests/test_fcfg.py index d9767ed..dd31c03 100644 --- a/pyformlang/fcfg/tests/test_fcfg.py +++ b/pyformlang/fcfg/tests/test_fcfg.py @@ -1,4 +1,6 @@ -"""Test a FCFG""" +"""Tests for FCFG.""" + +import pytest from pyformlang.cfg import Variable, Terminal, Production from pyformlang.cfg import DerivationDoesNotExistError @@ -8,7 +10,6 @@ from pyformlang.fcfg.feature_production import FeatureProduction from pyformlang.fcfg.feature_structure import FeatureStructure from pyformlang.fcfg.state import State, StateProcessed -import pytest @pytest.fixture @@ -31,10 +32,10 @@ def fcfg_text() -> str: class TestFCFG: - """Test a FCFG""" + """Test a FCFG.""" - def test_creation(self): - """ Tests creation of FCFG """ + def test_creation(self) -> None: + """Tests creation of FCFG.""" variable0 = Variable(0) terminal0 = Terminal("a") prod0 = Production(variable0, [terminal0, Terminal("A"), Variable(1)]) @@ -46,8 +47,9 @@ def test_creation(self): assert len(fcfg.feature_productions) == 1 assert fcfg.productions == fcfg.feature_productions assert fcfg.is_empty() - assert all(isinstance(prod, FeatureProduction) - for prod in fcfg.productions) + assert all( + isinstance(prod, FeatureProduction) for prod in fcfg.productions + ) fcfg = FCFG() assert fcfg is not None @@ -57,28 +59,32 @@ def test_creation(self): assert len(fcfg.feature_productions) == 0 assert fcfg.is_empty() - def test_contains(self): - """Test containment""" + def test_contains(self) -> None: + """Test containment.""" # 1st: S -> NP VP agreement = FeatureStructure() np_feat = FeatureStructure() np_feat.add_content("AGREEMENT", agreement) vp_feat = FeatureStructure() vp_feat.add_content("AGREEMENT", agreement) - fp1 = FeatureProduction(Variable("S"), - [Variable("NP"), Variable("VP")], - FeatureStructure(), - [np_feat, vp_feat]) + fp1 = FeatureProduction( + Variable("S"), + [Variable("NP"), Variable("VP")], + FeatureStructure(), + [np_feat, vp_feat], + ) # Second: S -> Aux NP VP agreement = FeatureStructure() aux_feat = FeatureStructure() aux_feat.add_content("AGREEMENT", agreement) np_feat = FeatureStructure() np_feat.add_content("AGREEMENT", agreement) - fp2 = FeatureProduction(Variable("S"), - [Variable("Aux"), Variable("NP"), Variable("VP")], - FeatureStructure(), - [aux_feat, np_feat, FeatureStructure()]) + fp2 = FeatureProduction( + Variable("S"), + [Variable("Aux"), Variable("NP"), Variable("VP")], + FeatureStructure(), + [aux_feat, np_feat, FeatureStructure()], + ) # Third: NP -> Det Nominal agreement = FeatureStructure() det_feat = FeatureStructure() @@ -87,112 +93,117 @@ def test_contains(self): np_feat.add_content("AGREEMENT", agreement) nominal_feat = FeatureStructure() nominal_feat.add_content("AGREEMENT", agreement) - fp3 = FeatureProduction(Variable("NP"), - [Variable("Det"), Variable("Nominal")], - np_feat, - [det_feat, nominal_feat]) + fp3 = FeatureProduction( + Variable("NP"), + [Variable("Det"), Variable("Nominal")], + np_feat, + [det_feat, nominal_feat], + ) # Forth: Aux -> do agreement = FeatureStructure() agreement.add_content("NUMBER", FeatureStructure("pl")) agreement.add_content("PERSON", FeatureStructure("3rd")) feat = FeatureStructure() feat.add_content("AGREEMENT", agreement) - fp4 = FeatureProduction(Variable("Aux"), - [Terminal("do")], - feat, - [FeatureStructure()]) + fp4 = FeatureProduction( + Variable("Aux"), [Terminal("do")], feat, [FeatureStructure()] + ) # 5: Aux -> does agreement = FeatureStructure() agreement.add_content("NUMBER", FeatureStructure("sg")) agreement.add_content("PERSON", FeatureStructure("3rd")) feat = FeatureStructure() feat.add_content("AGREEMENT", agreement) - fp5 = FeatureProduction(Variable("Aux"), - [Terminal("does")], - feat, - [FeatureStructure()]) + fp5 = FeatureProduction( + Variable("Aux"), [Terminal("does")], feat, [FeatureStructure()] + ) # 6: Det -> this agreement = FeatureStructure() agreement.add_content("NUMBER", FeatureStructure("sg")) feat = FeatureStructure() feat.add_content("AGREEMENT", agreement) - fp6 = FeatureProduction(Variable("Det"), - [Terminal("this")], - feat, - [FeatureStructure()]) + fp6 = FeatureProduction( + Variable("Det"), [Terminal("this")], feat, [FeatureStructure()] + ) # 7: Det -> these agreement = FeatureStructure() agreement.add_content("NUMBER", FeatureStructure("pl")) feat = FeatureStructure() feat.add_content("AGREEMENT", agreement) - fp7 = FeatureProduction(Variable("Det"), - [Terminal("these")], - feat, - [FeatureStructure()]) + fp7 = FeatureProduction( + Variable("Det"), [Terminal("these")], feat, [FeatureStructure()] + ) # 8: VP -> Verb agreement = FeatureStructure() vp_feat = FeatureStructure() vp_feat.add_content("AGREEMENT", agreement) verb_feat = FeatureStructure() verb_feat.add_content("AGREEMENT", agreement) - fp8 = FeatureProduction(Variable("VP"), - [Variable("Verb")], - vp_feat, - [verb_feat]) + fp8 = FeatureProduction( + Variable("VP"), [Variable("Verb")], vp_feat, [verb_feat] + ) assert "AGREEMENT" in str(fp8) # 9: Verb -> serve agreement = FeatureStructure() agreement.add_content("NUMBER", FeatureStructure("pl")) feat = FeatureStructure() feat.add_content("AGREEMENT", agreement) - fp9 = FeatureProduction(Variable("Verb"), - [Terminal("serve")], - feat, - [FeatureStructure()]) + fp9 = FeatureProduction( + Variable("Verb"), [Terminal("serve")], feat, [FeatureStructure()] + ) # 10: Verb -> serves agreement = FeatureStructure() agreement.add_content("NUMBER", FeatureStructure("sg")) agreement.add_content("PERSON", FeatureStructure("3rd")) feat = FeatureStructure() feat.add_content("AGREEMENT", agreement) - fp10 = FeatureProduction(Variable("Verb"), - [Terminal("serves")], - feat, - [FeatureStructure()]) + fp10 = FeatureProduction( + Variable("Verb"), [Terminal("serves")], feat, [FeatureStructure()] + ) # 11: Noun -> flight agreement = FeatureStructure() agreement.add_content("NUMBER", FeatureStructure("sg")) feat = FeatureStructure() feat.add_content("AGREEMENT", agreement) - fp11 = FeatureProduction(Variable("Noun"), - [Terminal("flight")], - feat, - [FeatureStructure()]) + fp11 = FeatureProduction( + Variable("Noun"), [Terminal("flight")], feat, [FeatureStructure()] + ) # 12: Noun -> flight agreement = FeatureStructure() agreement.add_content("NUMBER", FeatureStructure("pl")) feat = FeatureStructure() feat.add_content("AGREEMENT", agreement) - fp12 = FeatureProduction(Variable("Noun"), - [Terminal("flights")], - feat, - [FeatureStructure()]) + fp12 = FeatureProduction( + Variable("Noun"), [Terminal("flights")], feat, [FeatureStructure()] + ) # 13: Nominal -> Noun agreement = FeatureStructure() nominal_feat = FeatureStructure() nominal_feat.add_content("AGREEMENT", agreement) noun_feat = FeatureStructure() noun_feat.add_content("AGREEMENT", agreement) - fp13 = FeatureProduction(Variable("Nominal"), - [Variable("Noun")], - nominal_feat, - [noun_feat]) - productions = [fp1, fp2, fp3, fp4, fp5, fp6, fp7, fp8, fp9, fp10, fp11, - fp12, fp13] + fp13 = FeatureProduction( + Variable("Nominal"), [Variable("Noun")], nominal_feat, [noun_feat] + ) + productions = [ + fp1, + fp2, + fp3, + fp4, + fp5, + fp6, + fp7, + fp8, + fp9, + fp10, + fp11, + fp12, + fp13, + ] fcfg = FCFG(start_symbol=Variable("S"), productions=productions) self._sub_tests_contains1(fcfg) - def _sub_tests_contains1(self, fcfg): + def _sub_tests_contains1(self, fcfg: FCFG) -> None: assert fcfg.contains(["this", "flight", "serves"]) assert ["this", "flight", "serves"] in fcfg assert fcfg.contains(["these", "flights", "serve"]) @@ -200,46 +211,48 @@ def _sub_tests_contains1(self, fcfg): assert not fcfg.contains(["this", "flight", "serve"]) assert not fcfg.contains(["this", "flights", "serve"]) - def test_contains2(self): - """Test containment""" + def test_contains2(self) -> None: + """Test containment.""" # 1st: S -> NP number = FeatureStructure("sg") np_feat = FeatureStructure() np_feat.add_content("NUMBER", number) - fp1 = FeatureProduction(Variable("S"), - [Variable("NP")], - FeatureStructure(), - [np_feat]) + fp1 = FeatureProduction( + Variable("S"), [Variable("NP")], FeatureStructure(), [np_feat] + ) # 2nd: NP -> flights number = FeatureStructure("pl") np_feat = FeatureStructure() np_feat.add_content("NUMBER", number) - fp2 = FeatureProduction(Variable("NP"), - [Terminal("flights")], - np_feat, - [FeatureStructure()]) + fp2 = FeatureProduction( + Variable("NP"), [Terminal("flights")], np_feat, [FeatureStructure()] + ) assert "NUMBER" in str(fp2) fcfg = FCFG(start_symbol=Variable("S"), productions=[fp1, fp2]) assert not fcfg.contains(["flights"]) - def test_state(self): - """Test functions on states""" + def test_state(self) -> None: + """Test functions on states.""" fs1 = FeatureStructure() fs1.add_content("NUMBER", FeatureStructure("sg")) - state0 = State(FeatureProduction(Variable("S"), [], fs1, []), - (0, 0, 0), - fs1, - ParseTree(Variable("S"))) + state0 = State( + FeatureProduction(Variable("S"), [], fs1, []), + (0, 0, 0), + fs1, + ParseTree(Variable("S")), + ) processed = StateProcessed(1) - state1 = State(FeatureProduction(Variable("S"), [], fs1, []), - (0, 0, 0), - fs1, - ParseTree(Variable("S"))) + state1 = State( + FeatureProduction(Variable("S"), [], fs1, []), + (0, 0, 0), + fs1, + ParseTree(Variable("S")), + ) assert processed.add(0, state0) assert not processed.add(0, state1) - def test_from_text(self, fcfg_text: str): - """Test containment from a text description""" + def test_from_text(self, fcfg_text: str) -> None: + """Test containment from a text description.""" fcfg = FCFG.from_text(fcfg_text) self._sub_tests_contains1(fcfg) parse_tree = fcfg.get_parse_tree(["this", "flight", "serves"]) @@ -247,8 +260,8 @@ def test_from_text(self, fcfg_text: str): fcfg.get_parse_tree(["these", "flight", "serves"]) assert "Det" in str(parse_tree) - def test_copy(self, fcfg_text: str): - """Test copying of FCFG""" + def test_copy(self, fcfg_text: str) -> None: + """Test copying of FCFG.""" fcfg = FCFG.from_text(fcfg_text) fcfg_copy = fcfg.copy() assert fcfg.variables == fcfg_copy.variables @@ -257,27 +270,29 @@ def test_copy(self, fcfg_text: str): assert fcfg.start_symbol == fcfg_copy.start_symbol assert fcfg is not fcfg_copy - def test_get_leftmost_derivation(self): + def test_get_leftmost_derivation(self) -> None: ter_a = Terminal("a") ter_b = Terminal("b") var_s = Variable("S") var_a = Variable("A") var_b = Variable("B") var_c = Variable("C") - productions = [Production(var_s, [var_c, var_b]), - Production(var_c, [var_a, var_a]), - Production(var_a, [ter_a]), - Production(var_b, [ter_b]) - ] + productions = [ + Production(var_s, [var_c, var_b]), + Production(var_c, [var_a, var_a]), + Production(var_a, [ter_a]), + Production(var_b, [ter_b]), + ] fcfg = FCFG(productions=productions, start_symbol=var_s) parse_tree = fcfg.get_cnf_parse_tree([ter_a, ter_a, ter_b]) derivation = parse_tree.get_leftmost_derivation() - assert derivation == \ - [[var_s], - [var_c, var_b], - [var_a, var_a, var_b], - [ter_a, var_a, var_b], - [ter_a, ter_a, var_b], - [ter_a, ter_a, ter_b]] + assert derivation == [ + [var_s], + [var_c, var_b], + [var_a, var_a, var_b], + [ter_a, var_a, var_b], + [ter_a, ter_a, var_b], + [ter_a, ter_a, ter_b], + ] with pytest.raises(DerivationDoesNotExistError): fcfg.get_cnf_parse_tree([]) diff --git a/pyformlang/fcfg/tests/test_feature_structure.py b/pyformlang/fcfg/tests/test_feature_structure.py index a15225e..9ebd8c8 100644 --- a/pyformlang/fcfg/tests/test_feature_structure.py +++ b/pyformlang/fcfg/tests/test_feature_structure.py @@ -1,26 +1,31 @@ -"""Testing of the feature structure""" -from pyformlang.fcfg.feature_structure import \ - (FeatureStructure, - PathDoesNotExistError, - ContentAlreadyExistsError, - FeatureStructuresNotCompatibleError) +"""Testing of the feature structure.""" + import pytest +from pyformlang.fcfg.feature_structure import ( + FeatureStructure, + PathDoesNotExistError, + ContentAlreadyExistsError, + FeatureStructuresNotCompatibleError, +) + -def _get_agreement_subject_number_person(): - fs2 = FeatureStructure.from_text("AGREEMENT=(1)[NUMBER=sg, PERSON=3], SUBJECT=[AGREEMENT->(1)]") +def _get_agreement_subject_number_person() -> FeatureStructure: + fs2 = FeatureStructure.from_text( + "AGREEMENT=(1)[NUMBER=sg, PERSON=3], SUBJECT=[AGREEMENT->(1)]" + ) return fs2 class TestFeatureStructure: - """Testing of the feature structure""" + """Testing of the feature structure.""" - def test_creation(self): - """Test of creation""" + def test_creation(self) -> None: + """Test of creation.""" feature_structure = FeatureStructure() assert len(feature_structure.content) == 0 - assert feature_structure.pointer == None - assert feature_structure.get_feature_by_path().value == None + assert feature_structure.pointer is None + assert feature_structure.get_feature_by_path().value is None with pytest.raises(PathDoesNotExistError): feature_structure.get_feature_by_path(["NUMBER"]) feature_structure.add_content("NUMBER", FeatureStructure("sg")) @@ -28,51 +33,59 @@ def test_creation(self): with pytest.raises(ContentAlreadyExistsError): feature_structure.add_content("NUMBER", FeatureStructure("sg")) feature_structure = _get_agreement_subject_number_person() - assert feature_structure.get_feature_by_path(["SUBJECT", "AGREEMENT", "NUMBER"]).value == "sg" - - def test_unify1(self): - """First tests to unify""" + assert ( + feature_structure.get_feature_by_path( + ["SUBJECT", "AGREEMENT", "NUMBER"] + ).value + == "sg" + ) + + def test_unify1(self) -> None: + """First tests to unify.""" left = FeatureStructure() right = FeatureStructure() left.unify(right) assert len(left.content) == len(right.content) - def test_unify2(self): - """Second test to unify""" + def test_unify2(self) -> None: + """Second test to unify.""" left = FeatureStructure("pl") right = FeatureStructure("sg") with pytest.raises(FeatureStructuresNotCompatibleError): left.unify(right) - def test_unify3(self): - """Test to unify""" + def test_unify3(self) -> None: + """Test to unify.""" left = FeatureStructure() right = FeatureStructure("sg") left.unify(right) assert len(left.content) == len(right.content) assert left.value == right.value - def test_unify4(self): - """Test to unify""" + def test_unify4(self) -> None: + """Test to unify.""" left = FeatureStructure("pl") right = FeatureStructure() left.unify(right) assert len(left.content) == len(right.content) assert left.value == right.value - def test_unify5(self): - """Test to unify""" + def test_unify5(self) -> None: + """Test to unify.""" left = FeatureStructure() right = FeatureStructure() right.add_content("NUMBER", FeatureStructure("sg")) left.unify(right) assert len(left.content) == len(right.content) assert left.value == right.value - assert left.get_feature_by_path(["NUMBER"]).value == right.get_feature_by_path(["NUMBER"]).value + assert ( + left.get_feature_by_path(["NUMBER"]).value + == right.get_feature_by_path(["NUMBER"]).value + ) assert left.get_feature_by_path(["NUMBER"]).value == "sg" - def test_unify6(self): - """Test to unify""" + def test_unify6(self) -> None: + """Test to unify.""" left = FeatureStructure() left.add_content("PERSON", FeatureStructure("M")) right = FeatureStructure() @@ -80,11 +93,14 @@ def test_unify6(self): left.unify(right) assert len(left.content) >= len(right.content) assert left.value == right.value - assert left.get_feature_by_path(["NUMBER"]).value == right.get_feature_by_path(["NUMBER"]).value + assert ( + left.get_feature_by_path(["NUMBER"]).value + == right.get_feature_by_path(["NUMBER"]).value + ) assert left.get_feature_by_path(["NUMBER"]).value == "sg" - def test_unify7(self): - """Test to unify""" + def test_unify7(self) -> None: + """Test to unify.""" left = FeatureStructure() agreement_left = FeatureStructure() agreement_left.add_content("NUMBER", FeatureStructure("sg")) @@ -95,17 +111,25 @@ def test_unify7(self): right = FeatureStructure() right.add_content("SUBJECT", FeatureStructure()) right.add_content_path("AGREEMENT", FeatureStructure(), ["SUBJECT"]) - right.add_content_path("PERSON", FeatureStructure("3rd"), ["SUBJECT", "AGREEMENT"]) + right.add_content_path( + "PERSON", FeatureStructure("3rd"), ["SUBJECT", "AGREEMENT"] + ) left.unify(right) - assert left.get_feature_by_path(["AGREEMENT", "PERSON"]).value == \ - right.get_feature_by_path(["AGREEMENT", "PERSON"]).value - assert left.get_feature_by_path(["SUBJECT", "AGREEMENT", "PERSON"]).value == \ - right.get_feature_by_path(["AGREEMENT", "PERSON"]).value - assert left.get_feature_by_path(["SUBJECT", "AGREEMENT", "PERSON"]).value == \ - "3rd" - - def test_subsumes1(self): - """Test to subsume""" + assert ( + left.get_feature_by_path(["AGREEMENT", "PERSON"]).value + == right.get_feature_by_path(["AGREEMENT", "PERSON"]).value + ) + assert ( + left.get_feature_by_path(["SUBJECT", "AGREEMENT", "PERSON"]).value + == right.get_feature_by_path(["AGREEMENT", "PERSON"]).value + ) + assert ( + left.get_feature_by_path(["SUBJECT", "AGREEMENT", "PERSON"]).value + == "3rd" + ) + + def test_subsumes1(self) -> None: + """Test to subsume.""" fs0 = FeatureStructure() fs0.add_content("NUMBER", FeatureStructure("pl")) fs1 = FeatureStructure() @@ -161,8 +185,8 @@ def test_subsumes1(self): assert not fs5.subsumes(fs3) assert not fs5.subsumes(fs4) - def test_copy(self): - """Test to subsume""" + def test_copy(self) -> None: + """Test to subsume.""" fs1 = FeatureStructure() agreement = FeatureStructure() subject = FeatureStructure() @@ -181,14 +205,28 @@ def test_copy(self): copy_of_copy = fs1_copy2.copy() self._assertions_test_copy(copy_of_copy) - def _assertions_test_copy(self, fs1_copy): - assert fs1_copy.get_feature_by_path(["AGREEMENT", "NUMBER"]).value == "sg" - assert fs1_copy.get_feature_by_path(["AGREEMENT", "PERSON"]).value == "3" - assert fs1_copy.get_feature_by_path(["SUBJECT", "AGREEMENT", "NUMBER"]).value == "sg" - assert fs1_copy.get_feature_by_path(["SUBJECT", "AGREEMENT", "PERSON"]).value == "3" - - def test_paths(self): - """Test the path generation""" + def _assertions_test_copy(self, fs1_copy: FeatureStructure) -> None: + assert ( + fs1_copy.get_feature_by_path(["AGREEMENT", "NUMBER"]).value == "sg" + ) + assert ( + fs1_copy.get_feature_by_path(["AGREEMENT", "PERSON"]).value == "3" + ) + assert ( + fs1_copy.get_feature_by_path( + ["SUBJECT", "AGREEMENT", "NUMBER"] + ).value + == "sg" + ) + assert ( + fs1_copy.get_feature_by_path( + ["SUBJECT", "AGREEMENT", "PERSON"] + ).value + == "3" + ) + + def test_paths(self) -> None: + """Test the path generation.""" fs2 = _get_agreement_subject_number_person() assert len(fs2.get_all_paths()) == 4 representation = repr(fs2) diff --git a/pyformlang/finite_automaton/tests/test_deterministic_finite_automaton.py b/pyformlang/finite_automaton/tests/test_deterministic_finite_automaton.py index 84b7aaa..1b24df7 100644 --- a/pyformlang/finite_automaton/tests/test_deterministic_finite_automaton.py +++ b/pyformlang/finite_automaton/tests/test_deterministic_finite_automaton.py @@ -1,6 +1,4 @@ -""" -Tests for the deterministic finite automata -""" +"""Tests for the deterministic finite automata.""" import pytest @@ -12,14 +10,12 @@ class TestDeterministicFiniteAutomaton: - """ Tests for deterministic finite automata - """ + """Tests for deterministic finite automata.""" # pylint: disable=missing-function-docstring, protected-access - def test_can_create(self): - """ Test the creation of dfa - """ + def test_can_create(self) -> None: + """Test the creation of dfa.""" state0 = State("0") state1 = State("1") symb0 = Symbol("a") @@ -29,23 +25,25 @@ def test_can_create(self): transition_function.add_transition(state0, symb0, state1) start_state = state0 final_states = {state1} - dfa = DeterministicFiniteAutomaton(states, - input_symbols, - transition_function, - start_state, - final_states) + dfa = DeterministicFiniteAutomaton( + states, + input_symbols, + transition_function, + start_state, + final_states, + ) assert len(dfa.to_dict()) == 1 assert len(dfa) == 1 assert dfa is not None dfa = DeterministicFiniteAutomaton() assert dfa is not None - dfa = DeterministicFiniteAutomaton(start_state=state1, - final_states={state0, state1}) + dfa = DeterministicFiniteAutomaton( + start_state=state1, final_states={state0, state1} + ) assert dfa is not None - def test_add_transition(self): - """ Tests the addition of transitions - """ + def test_add_transition(self) -> None: + """Tests the addition of transitions.""" dfa = DeterministicFiniteAutomaton() assert len(dfa.states) == 0 state0 = State("0") @@ -56,9 +54,8 @@ def test_add_transition(self): assert len(dfa.symbols) == 1 assert len(list(dfa._transition_function.get_edges())) == 1 - def test_add_remove_start_final(self): - """ Tests the addition and removal of initial state and final states - """ + def test_add_remove_start_final(self) -> None: + """Tests the addition and removal of initial state and final states.""" dfa = DeterministicFiniteAutomaton() state0 = State("0") state1 = State("1") @@ -73,9 +70,8 @@ def test_add_remove_start_final(self): assert not dfa.is_final_state(state1) assert dfa.remove_final_state(state1) == 0 - def test_accepts(self): - """ Tests the acceptance of dfa - """ + def test_accepts(self) -> None: + """Tests the acceptance of dfa.""" dfa = get_example0() perform_tests_example0(dfa) dfa = get_example0_bis() @@ -94,13 +90,13 @@ def test_accepts(self): assert dfa.remove_start_state(0) == 1 assert not dfa.accepts(["a", "b", "c"]) - def test_copy(self): - """ Test the copy of a DFA """ + def test_copy(self) -> None: + """Test the copy of a DFA.""" dfa = get_example0().copy() perform_tests_example0(dfa) - def test_complement(self): - """ Tests the complement operation """ + def test_complement(self) -> None: + """Tests the complement operation.""" dfa = DeterministicFiniteAutomaton() symb_a = Symbol("a") symb_b = Symbol("b") @@ -118,19 +114,19 @@ def test_complement(self): assert dfa_comp.accepts([]) assert not dfa_comp.accepts([symb_a, symb_b]) - def test_big_minimize(self): + def test_big_minimize(self) -> None: dfa = DeterministicFiniteAutomaton() size = 1000 symb = Symbol("s") dfa.add_start_state(State(0)) dfa.add_final_state(State(size)) for i in range(size): - dfa.add_transition(State(i), symb, State(i+1)) + dfa.add_transition(State(i), symb, State(i + 1)) dfa = dfa.minimize() assert len(dfa.states) == size + 1 assert not dfa.accepts([symb]) - def test_big_minimize_reduce(self): + def test_big_minimize_reduce(self) -> None: dfa = DeterministicFiniteAutomaton() symb_0 = Symbol("0") symb_0_minus = Symbol("0-") @@ -161,17 +157,47 @@ def test_big_minimize_reduce(self): dfa.add_transition(states[1], symb_0_minus, states[5]) dfa.add_transition(states[6], symb_0_minus, states[7]) dfa.add_transition(states[3], symb_1_minus, states[4]) - assert not dfa.accepts(["0", "STAR", "0-", "STAR", "0-", "0", - "STAR", "0", "0", "STAR", "0-", "STAR", - "0-", "1-"]) + assert not dfa.accepts( + [ + "0", + "STAR", + "0-", + "STAR", + "0-", + "0", + "STAR", + "0", + "0", + "STAR", + "0-", + "STAR", + "0-", + "1-", + ] + ) dfa = dfa.minimize() - assert not dfa.accepts(["0", "STAR", "0-", "STAR", "0-", "0", - "STAR", "0", "0", "STAR", "0-", "STAR", - "0-", "1-"]) - - def test_minimize_repetition(self): + assert not dfa.accepts( + [ + "0", + "STAR", + "0-", + "STAR", + "0-", + "0", + "STAR", + "0", + "0", + "STAR", + "0-", + "STAR", + "0-", + "1-", + ] + ) + + def test_minimize_repetition(self) -> None: dfa = DeterministicFiniteAutomaton() - symb_a = Symbol('a') + symb_a = Symbol("a") symb_b = Symbol("b") symb_star = Symbol("star") states = [State(x) for x in range(9)] @@ -200,56 +226,54 @@ def test_minimize_repetition(self): dfa = dfa.minimize() assert dfa.accepts([symb_a, symb_star, symb_a]) - def test_not_cyclic(self): + def test_not_cyclic(self) -> None: dfa = DeterministicFiniteAutomaton() state0 = State(0) state1 = State(1) - symb_a = Symbol('a') + symb_a = Symbol("a") dfa.add_start_state(state0) dfa.add_transition(state0, symb_a, state1) assert dfa.is_acyclic() - def test_not_cyclic2(self): + def test_not_cyclic2(self) -> None: dfa = DeterministicFiniteAutomaton() state0 = State(0) state1 = State(1) - symb_a = Symbol('a') - symb_b = Symbol('b') + symb_a = Symbol("a") + symb_b = Symbol("b") dfa.add_start_state(state0) dfa.add_transition(state0, symb_a, state1) dfa.add_transition(state0, symb_b, state1) assert dfa.is_acyclic() - def test_epsilon_refused(self): + def test_epsilon_refused(self) -> None: dfa = DeterministicFiniteAutomaton() state0 = State(0) state1 = State(1) with pytest.raises(InvalidEpsilonTransitionError): dfa.add_transition(state0, Epsilon(), state1) - def test_cyclic(self): + def test_cyclic(self) -> None: dfa = DeterministicFiniteAutomaton() state0 = State(0) state1 = State(1) - symb_a = Symbol('a') + symb_a = Symbol("a") dfa.add_start_state(state0) dfa.add_transition(state0, symb_a, state1) dfa.add_transition(state1, symb_a, state0) assert not dfa.is_acyclic() - def test_equivalent(self): + def test_equivalent(self) -> None: dfa1 = get_dfa_example() dfa2 = DeterministicFiniteAutomaton() dfa2.add_transitions( - [("A", "c", "B"), - ("C", "d", "D"), - ("B", "S", "C"), - ("B", "c", "D")]) + [("A", "c", "B"), ("C", "d", "D"), ("B", "S", "C"), ("B", "c", "D")] + ) dfa2.add_start_state(State("A")) dfa2.add_final_state(State("D")) assert dfa2 != dfa1 - def test_word_generation(self): + def test_word_generation(self) -> None: dfa = get_dfa_example_for_word_generation() accepted_words = list(dfa.get_accepted_words()) assert [] in accepted_words @@ -257,7 +281,7 @@ def test_word_generation(self): assert [Symbol("b"), Symbol("d")] in accepted_words assert len(accepted_words) == 3 - def test_cyclic_word_generation(self): + def test_cyclic_word_generation(self) -> None: dfa = get_cyclic_dfa_example() accepted_words = list(dfa.get_accepted_words(5)) assert ["a", "f"] in accepted_words @@ -266,14 +290,14 @@ def test_cyclic_word_generation(self): assert ["a", "b", "d", "a", "f"] in accepted_words assert len(accepted_words) == 4 - def test_dfa_generating_no_words(self): + def test_dfa_generating_no_words(self) -> None: dfa = get_dfa_example_without_accepted_words() accepted_words = list(dfa.get_accepted_words()) assert not accepted_words -def get_example0(): - """ Gives a dfa """ +def get_example0() -> DeterministicFiniteAutomaton: + """Gives a dfa.""" dfa = DeterministicFiniteAutomaton() state0 = State(0) state1 = State(1) @@ -293,8 +317,8 @@ def get_example0(): return dfa -def get_example0_bis(): - """ Gives a dfa """ +def get_example0_bis() -> DeterministicFiniteAutomaton: + """Gives a dfa.""" dfa = DeterministicFiniteAutomaton() dfa.add_start_state(0) dfa.add_final_state(2) @@ -306,72 +330,72 @@ def get_example0_bis(): return dfa -def get_dfa_example(): - """ An example of DFA """ +def get_dfa_example() -> DeterministicFiniteAutomaton: + """An example of DFA.""" dfa1 = DeterministicFiniteAutomaton() dfa1.add_transitions( - [("A", "c", "B"), - ("C", "d", "D"), - ("B", "S", "C"), - ("B", "d", "D")]) + [("A", "c", "B"), ("C", "d", "D"), ("B", "S", "C"), ("B", "d", "D")] + ) dfa1.add_start_state(State("A")) dfa1.add_final_state(State("D")) return dfa1 -def get_dfa_example_for_word_generation(): - """ DFA example for the word generation test """ +def get_dfa_example_for_word_generation() -> DeterministicFiniteAutomaton: + """DFA example for the word generation test.""" dfa = DeterministicFiniteAutomaton() states = [State(x) for x in range(4)] symbol_a = Symbol("a") symbol_b = Symbol("b") symbol_c = Symbol("c") symbol_d = Symbol("d") - dfa.add_transitions([ - (states[0], symbol_a, states[1]), - (states[0], symbol_b, states[2]), - (states[1], symbol_a, states[1]), - (states[2], symbol_c, states[3]), - (states[2], symbol_d, states[3]), - ]) + dfa.add_transitions( + [ + (states[0], symbol_a, states[1]), + (states[0], symbol_b, states[2]), + (states[1], symbol_a, states[1]), + (states[2], symbol_c, states[3]), + (states[2], symbol_d, states[3]), + ] + ) dfa.add_start_state(states[0]) dfa.add_final_state(states[0]) dfa.add_final_state(states[3]) return dfa -def get_cyclic_dfa_example(): - """ Gets DFA example with several cycles on path to final """ - dfa = DeterministicFiniteAutomaton(start_state=0, - final_states={3}) - dfa.add_transitions([ - (0, "a", 1), - (1, "b", 2), - (2, "c", 2), - (2, "d", 0), - (2, "e", 1), - (1, "f", 3), - ]) +def get_cyclic_dfa_example() -> DeterministicFiniteAutomaton: + """Gets DFA example with several cycles on path to final.""" + dfa = DeterministicFiniteAutomaton(start_state=0, final_states={3}) + dfa.add_transitions( + [ + (0, "a", 1), + (1, "b", 2), + (2, "c", 2), + (2, "d", 0), + (2, "e", 1), + (1, "f", 3), + ] + ) return dfa -def get_dfa_example_without_accepted_words(): - """ DFA example accepting no words """ +def get_dfa_example_without_accepted_words() -> DeterministicFiniteAutomaton: + """DFA example accepting no words.""" dfa = DeterministicFiniteAutomaton() states = [State(x) for x in range(4)] symbol_a = Symbol("a") symbol_b = Symbol("b") - dfa.add_transitions([ - (states[0], symbol_a, states[1]), - (states[2], symbol_b, states[3]), - ]) + dfa.add_transitions( + [(states[0], symbol_a, states[1]), (states[2], symbol_b, states[3])] + ) dfa.add_start_state(states[0]) dfa.add_final_state(states[3]) return dfa -def perform_tests_example0(enfa: EpsilonNFA): - """ Tests for DFA from example 0 """ +def perform_tests_example0(enfa: EpsilonNFA) -> None: + """Tests for DFA from example 0.""" symb_a = Symbol("a") symb_b = Symbol("b") symb_c = Symbol("c") diff --git a/pyformlang/finite_automaton/tests/test_deterministic_transition_function.py b/pyformlang/finite_automaton/tests/test_deterministic_transition_function.py index 4ec0c8a..cf5fa3f 100644 --- a/pyformlang/finite_automaton/tests/test_deterministic_transition_function.py +++ b/pyformlang/finite_automaton/tests/test_deterministic_transition_function.py @@ -1,28 +1,25 @@ -""" -Test the transition functions -""" +"""Test the transition functions.""" import pytest from pyformlang.finite_automaton import DeterministicTransitionFunction from pyformlang.finite_automaton import State, Symbol, Epsilon -from pyformlang.finite_automaton import \ - DuplicateTransitionError, InvalidEpsilonTransitionError +from pyformlang.finite_automaton import ( + DuplicateTransitionError, + InvalidEpsilonTransitionError, +) class TestDeterministicTransitionFunction: - """ Tests the transitions functions - """ + """Tests the transitions functions.""" - def test_creation(self): - """ Tests the creation of transition functions - """ + def test_creation(self) -> None: + """Tests the creation of transition functions.""" transition_function = DeterministicTransitionFunction() assert transition_function is not None - def test_add_transitions(self): - """ Tests the addition of transitions - """ + def test_add_transitions(self) -> None: + """Tests the addition of transitions.""" transition_function = DeterministicTransitionFunction() s_from = State(10) s_to = State(11) @@ -38,9 +35,8 @@ def test_add_transitions(self): assert dte.symb_by == symb_by assert dte.s_to_old == s_to - def test_number_transitions(self): - """ Tests the number of transitions - """ + def test_number_transitions(self) -> None: + """Tests the number of transitions.""" transition_function = DeterministicTransitionFunction() assert transition_function.get_number_transitions() == 0 s_from = State(110) @@ -57,27 +53,21 @@ def test_number_transitions(self): transition_function.add_transition(s_to, symb_by, s_to_bis) assert transition_function.get_number_transitions() == 3 - def test_remove_transitions(self): - """ Tests the removal of transitions - """ + def test_remove_transitions(self) -> None: + """Tests the removal of transitions.""" transition_function = DeterministicTransitionFunction() s_from = State(10) s_to = State(11) symb_by = Symbol("abc") transition_function.add_transition(s_from, symb_by, s_to) - assert transition_function.remove_transition(s_from, - symb_by, - s_to) == 1 + assert transition_function.remove_transition(s_from, symb_by, s_to) == 1 assert transition_function.get_number_transitions() == 0 assert transition_function(s_to, symb_by) == set() assert transition_function(s_from, symb_by) == set() - assert transition_function.remove_transition(s_from, - symb_by, - s_to) == 0 + assert transition_function.remove_transition(s_from, symb_by, s_to) == 0 - def test_call(self): - """ Tests the call of a transition function - """ + def test_call(self) -> None: + """Tests the call of a transition function.""" transition_function = DeterministicTransitionFunction() s_from = State(0) s_to = State(1) @@ -86,8 +76,8 @@ def test_call(self): assert transition_function(s_from, symb_by) == {s_to} assert transition_function(s_to, symb_by) == set() - def test_get_next_state(self): - """ Tests the transition function call to get a single state """ + def test_get_next_state(self) -> None: + """Tests the transition function call to get a single state.""" transition_function = DeterministicTransitionFunction() s_from = State(0) s_to = State(1) @@ -96,8 +86,8 @@ def test_get_next_state(self): assert transition_function.get_next_state(s_from, symb_by) == s_to assert transition_function.get_next_state(s_to, symb_by) is None - def test_invalid_epsilon(self): - """ Tests invalid transition """ + def test_invalid_epsilon(self) -> None: + """Tests invalid transition.""" transition_function = DeterministicTransitionFunction() s_from = State(0) s_to = State(1) @@ -105,8 +95,8 @@ def test_invalid_epsilon(self): with pytest.raises(InvalidEpsilonTransitionError): transition_function.add_transition(s_from, epsilon, s_to) - def test_get_transitions_from(self): - """ Tests iteration of transitions from specified state """ + def test_get_transitions_from(self) -> None: + """Tests iteration of transitions from specified state.""" transition_function = DeterministicTransitionFunction() states = [State(x) for x in range(0, 4)] symbol_a = Symbol("a") diff --git a/pyformlang/finite_automaton/tests/test_epsilon.py b/pyformlang/finite_automaton/tests/test_epsilon.py index 7dd5add..c6aa379 100644 --- a/pyformlang/finite_automaton/tests/test_epsilon.py +++ b/pyformlang/finite_automaton/tests/test_epsilon.py @@ -1,16 +1,14 @@ -""" -Tests for epsilon transitions -""" +"""Tests for epsilon transitions.""" from pyformlang.finite_automaton import Epsilon from pyformlang.finite_automaton import State, Symbol class TestEpsilon: - """ Tests for epsilon transitions """ + """Tests for epsilon transitions.""" - def test_epsilon(self): - """ Generic tests for epsilon """ + def test_epsilon(self) -> None: + """Generic tests for epsilon.""" eps0 = Epsilon() eps1 = Epsilon() symb = Symbol(0) diff --git a/pyformlang/finite_automaton/tests/test_epsilon_nfa.py b/pyformlang/finite_automaton/tests/test_epsilon_nfa.py index b498b8c..e480389 100644 --- a/pyformlang/finite_automaton/tests/test_epsilon_nfa.py +++ b/pyformlang/finite_automaton/tests/test_epsilon_nfa.py @@ -1,7 +1,6 @@ -""" -Tests for epsilon NFA -""" +"""Tests for epsilon NFA.""" +from typing import List, Tuple import copy import networkx @@ -12,13 +11,13 @@ class TestEpsilonNFA: - """ Tests epsilon NFA """ + """Tests epsilon NFA.""" # pylint: disable=missing-function-docstring # pylint: disable=too-many-statements, too-many-public-methods - def test_eclose(self): - """ Test of the epsilon closure """ + def test_eclose(self) -> None: + """Test of the epsilon closure.""" states = [State(x) for x in range(8)] epsilon = Epsilon() symb_a = Symbol("a") @@ -39,15 +38,15 @@ def test_eclose(self): assert enfa.remove_transition(states[1], epsilon, states[4]) == 1 assert not enfa.is_deterministic() - def test_accept(self): - """ Test the acceptance """ + def test_accept(self) -> None: + """Test the acceptance.""" self._perform_tests_digits(False) - def test_copy(self): - """ Tests the copy of enda """ + def test_copy(self) -> None: + """Tests the copy of enda.""" self._perform_tests_digits(True) - def _perform_tests_digits(self, should_copy: bool = False): + def _perform_tests_digits(self, should_copy: bool = False) -> None: enfa, digits, epsilon, plus, minus, point = get_digits_enfa() if should_copy: enfa = copy.copy(enfa) @@ -70,8 +69,8 @@ def _perform_tests_digits(self, should_copy: bool = False): assert not enfa.accepts(["."]) assert not enfa.accepts(["+"]) - def test_deterministic(self): - """ Tests the transformation to a dfa""" + def test_deterministic(self) -> None: + """Tests the transformation to a dfa.""" enfa, digits, _, plus, minus, point = get_digits_enfa() dfa = DeterministicFiniteAutomaton.from_epsilon_nfa(enfa) assert dfa.is_deterministic() @@ -87,8 +86,8 @@ def test_deterministic(self): assert not dfa.accepts([point]) assert not dfa.accepts([plus]) - def test_union0(self): - """ Tests the union of two epsilon NFA """ + def test_union0(self) -> None: + """Tests the union of two epsilon NFA.""" enfa0 = get_enfa_example0() enfa1 = get_enfa_example1() symb_a = Symbol("a") @@ -101,10 +100,10 @@ def test_union0(self): assert not enfa.accepts([symb_a]) assert not enfa.accepts([]) - def test_union1(self): - """ - Tests the union of three ENFAs. - Union is (a*b)|(ab+)|c + def test_union1(self) -> None: + """Tests the union of three ENFAs. + + Union is (a*b)|(ab+)|c. """ enfa0 = get_enfa_example0() enfa1 = get_enfa_example1() @@ -119,8 +118,8 @@ def test_union1(self): assert ["c"] in accepted_words assert len(accepted_words) == 5 - def test_concatenate0(self): - """ Tests the concatenation of two epsilon NFA """ + def test_concatenate0(self) -> None: + """Tests the concatenation of two epsilon NFA.""" enfa0 = get_enfa_example0() enfa1 = get_enfa_example1() symb_a = Symbol("a") @@ -134,10 +133,10 @@ def test_concatenate0(self): assert not enfa.accepts([symb_b]) assert not enfa.accepts([]) - def test_concatenate1(self): - """ - Tests the concatenation of three ENFAs. - Concatenation is a*bc((ab+)|c) + def test_concatenate1(self) -> None: + """Tests the concatenation of three ENFAs. + + Concatenation is a*bc((ab+)|c). """ enfa0 = get_enfa_example0() enfa1 = get_enfa_example1() @@ -150,8 +149,8 @@ def test_concatenate1(self): assert ["b", "c", "a", "b"] in accepted_words assert len(accepted_words) == 3 - def test_kleene0(self): - """ Tests the kleene star of an epsilon NFA """ + def test_kleene0(self) -> None: + """Tests the kleene star of an epsilon NFA.""" enfa0 = get_enfa_example0() symb_a = Symbol("a") symb_b = Symbol("b") @@ -164,10 +163,10 @@ def test_kleene0(self): assert not enfa.accepts([symb_a]) assert not enfa.accepts([symb_a, symb_b, symb_a]) - def test_kleene1(self): - """ - Tests the kleene star of an ENFA. - Expression is ((ab+)|c)* + def test_kleene1(self) -> None: + """Tests the kleene star of an ENFA. + + Expression is ((ab+)|c)*. """ enfa = get_enfa_example2() enfa = enfa.kleene_star() @@ -181,8 +180,8 @@ def test_kleene1(self): assert ["c"] * (i + 1) in accepted_words assert len(accepted_words) == 8 - def test_complement(self): - """ Tests the complement operation """ + def test_complement(self) -> None: + """Tests the complement operation.""" enfa = EpsilonNFA() state0 = State(0) state1 = State(1) @@ -195,8 +194,8 @@ def test_complement(self): enfa_comp = -enfa assert not enfa_comp.accepts([symb_a]) - def test_intersection(self): - """ Tests the intersection of two enfas """ + def test_intersection(self) -> None: + """Tests the intersection of two enfas.""" enfa0 = get_enfa_example0() symb_a = Symbol("a") symb_b = Symbol("b") @@ -224,8 +223,8 @@ def test_intersection(self): assert not enfa.accepts([]) assert not enfa.accepts([symb_a, symb_a, symb_b]) - def test_difference(self): - """ Tests the intersection of two languages """ + def test_difference(self) -> None: + """Tests the intersection of two languages.""" enfa0 = get_enfa_example0() enfa1 = get_enfa_example1() symb_a = Symbol("a") @@ -246,8 +245,8 @@ def test_difference(self): assert not enfa.accepts([symb_b]) assert not enfa.accepts([symb_c]) - def test_reverse(self): - """ Test the reversal of a language """ + def test_reverse(self) -> None: + """Test the reversal of a language.""" enfa0 = get_enfa_example0() symb_a = Symbol("a") symb_b = Symbol("b") @@ -259,8 +258,8 @@ def test_reverse(self): assert not enfa.accepts([symb_a]) assert not enfa.accepts([]) - def test_empty(self): - """ Tests the emptiness of a finite automaton """ + def test_empty(self) -> None: + """Tests the emptiness of a finite automaton.""" assert get_enfa_example0() assert not get_enfa_example1().is_empty() enfa = EpsilonNFA() @@ -268,14 +267,14 @@ def test_empty(self): enfa.add_start_state(state0) assert enfa.is_empty() state1 = State(1) - symb_a = Symbol('a') + symb_a = Symbol("a") enfa.add_transition(state0, symb_a, state1) assert enfa.is_empty() enfa.add_final_state(state1) assert not enfa.is_empty() - def test_minimization(self): - """ Tests the minimization algorithm """ + def test_minimization(self) -> None: + """Tests the minimization algorithm.""" enfa = get_enfa_example0_bis() symb_a = Symbol("a") symb_b = Symbol("b") @@ -300,8 +299,8 @@ def test_minimization(self): assert len(enfa.states) == 1 assert not enfa.accepts([]) - def test_to_fst(self): - """ Tests to turn a ENFA into a FST """ + def test_to_fst(self) -> None: + """Tests to turn a ENFA into a FST.""" enfa = EpsilonNFA() fst = enfa.to_fst() assert len(fst.states) == 0 @@ -367,21 +366,21 @@ def test_to_fst(self): trans0 = list(fst.translate(["c"])) assert trans0 == [["c"]] - def test_cyclic(self): + def test_cyclic(self) -> None: enfa = EpsilonNFA() state0 = State(0) state1 = State(1) - symb_a = Symbol('a') + symb_a = Symbol("a") enfa.add_start_state(state0) enfa.add_transition(state0, symb_a, state1) enfa.add_transition(state1, Epsilon(), state0) assert not enfa.is_acyclic() - def test_export_networkx(self): + def test_export_networkx(self) -> None: enfa = EpsilonNFA() state0 = State("0") state1 = State(1) - symb_a = Symbol('a') + symb_a = Symbol("a") enfa.add_start_state(state0) enfa.add_final_state(state1) enfa.add_transition(state0, symb_a, state1) @@ -397,11 +396,11 @@ def test_export_networkx(self): assert graph.nodes[1]["is_final"] enfa.write_as_dot("enfa.dot") - def test_import_networkx(self): + def test_import_networkx(self) -> None: enfa = EpsilonNFA() state0 = State("0") state1 = State(1) - symb_a = Symbol('a') + symb_a = Symbol("a") enfa.add_start_state(state0) enfa.add_final_state(state1) enfa.add_transition(state0, symb_a, state1) @@ -412,11 +411,11 @@ def test_import_networkx(self): assert enfa_from_nx.accepts([symb_a, symb_a]) assert not enfa_from_nx.accepts([]) - def test_iter(self): + def test_iter(self) -> None: enfa = EpsilonNFA() state0 = State("0") state1 = State(1) - symb_a = Symbol('a') + symb_a = Symbol("a") enfa.add_start_state(state0) enfa.add_final_state(state1) enfa.add_transition(state0, symb_a, state1) @@ -429,11 +428,11 @@ def test_iter(self): assert ("0", "a", 1) in enfa assert counter == 2 - def test_equivalent(self): + def test_equivalent(self) -> None: enfa0 = EpsilonNFA() state0 = State("0") state1 = State(1) - symb_a = Symbol('a') + symb_a = Symbol("a") enfa0.add_start_state(state0) enfa0.add_final_state(state1) enfa0.add_transition(state0, symb_a, state1) @@ -447,11 +446,11 @@ def test_equivalent(self): dfa1 = DeterministicFiniteAutomaton.from_epsilon_nfa(enfa1) assert dfa0.is_equivalent_to(dfa1) - def test_non_equivalent(self): + def test_non_equivalent(self) -> None: enfa0 = EpsilonNFA() state0 = State("0") state1 = State(1) - symb_a = Symbol('a') + symb_a = Symbol("a") enfa0.add_start_state(state0) enfa0.add_final_state(state1) enfa0.add_transition(state0, symb_a, state1) @@ -465,11 +464,11 @@ def test_non_equivalent(self): dfa1 = DeterministicFiniteAutomaton.from_epsilon_nfa(enfa1) assert not dfa0.is_equivalent_to(dfa1) - def test_get_as_dict(self): + def test_get_as_dict(self) -> None: enfa0 = EpsilonNFA() state0 = State("0") state1 = State(1) - symb_a = Symbol('a') + symb_a = Symbol("a") enfa0.add_start_state(state0) enfa0.add_final_state(state1) enfa0.add_transition(state0, symb_a, state1) @@ -479,32 +478,34 @@ def test_get_as_dict(self): assert symb_a in d_enfa[state0] assert state1 in d_enfa[state0][symb_a] - def test_len(self): + def test_len(self) -> None: enfa = get_enfa_example1() assert len(enfa) == 1 - def test_call(self): - """ Tests the call of the transition function of the ENFA """ + def test_call(self) -> None: + """Tests the call of the transition function of the ENFA.""" enfa = get_enfa_example1() assert enfa(2, "c") == {3} assert not enfa(3, "a") assert not enfa(2313, "qwe") - def test_get_transitions_from(self): - """ Tests the transition obtaining from the given state """ + def test_get_transitions_from(self) -> None: + """Tests the transition obtaining from the given state.""" enfa = get_enfa_example1() assert list(enfa.get_transitions_from(2)) == [("c", 3)] assert not list(enfa.get_transitions_from(3)) assert not list(enfa.get_transitions_from(4210)) - def test_remove_epsilon_transitions(self): + def test_remove_epsilon_transitions(self) -> None: enfa = EpsilonNFA() - enfa.add_transitions([ - ("a", "epsilon", "b"), - ("b", "t", "c"), - ("a", "u", "c"), - ("b", "epsilon", "d") - ]) + enfa.add_transitions( + [ + ("a", "epsilon", "b"), + ("b", "t", "c"), + ("a", "u", "c"), + ("b", "epsilon", "d"), + ] + ) assert enfa.get_number_transitions() == 4 enfa.add_start_state("a") enfa.add_final_state("b") @@ -517,7 +518,7 @@ def test_remove_epsilon_transitions(self): dfa1 = DeterministicFiniteAutomaton.from_epsilon_nfa(enfa) assert dfa0.is_equivalent_to(dfa1) - def test_word_generation(self): + def test_word_generation(self) -> None: enfa = get_enfa_example_for_word_generation() accepted_words = list(enfa.get_accepted_words()) assert [] in accepted_words @@ -527,40 +528,45 @@ def test_word_generation(self): assert [Symbol("d"), Symbol("e"), Symbol("f")] in accepted_words assert len(accepted_words) == 5 - def test_cyclic_word_generation(self): + def test_cyclic_word_generation(self) -> None: enfa = get_cyclic_enfa_example() max_length = 10 - accepted_words = [[Symbol("a")] + - [Symbol("b")] * (i + 1) + - [Symbol("c")] - for i in range(max_length - 2)] + accepted_words = [ + [Symbol("a")] + [Symbol("b")] * (i + 1) + [Symbol("c")] + for i in range(max_length - 2) + ] actual_accepted_words = list(enfa.get_accepted_words(max_length)) assert accepted_words == actual_accepted_words - def test_epsilon_cycle_word_generation(self): + def test_epsilon_cycle_word_generation(self) -> None: enfa = get_epsilon_cycle_enfa_example() max_length = 4 accepted_words = list(enfa.get_accepted_words(max_length)) assert [] in accepted_words assert [Symbol("a"), Symbol("c")] in accepted_words assert [Symbol("a"), Symbol("b"), Symbol("c")] in accepted_words - assert [Symbol("a"), Symbol("b"), - Symbol("b"), Symbol("c")] in accepted_words + assert [ + Symbol("a"), + Symbol("b"), + Symbol("b"), + Symbol("c"), + ] in accepted_words assert len(accepted_words) == 4 - def test_max_length_zero_accepting_empty_string(self): + def test_max_length_zero_accepting_empty_string(self) -> None: enfa = get_enfa_example_for_word_generation() accepted_words = list(enfa.get_accepted_words(0)) assert accepted_words == [[]] - def test_max_length_zero_not_accepting_empty_string(self): + def test_max_length_zero_not_accepting_empty_string(self) -> None: enfa = get_cyclic_enfa_example() accepted_words = list(enfa.get_accepted_words(0)) assert not accepted_words -def get_digits_enfa(): - """ An epsilon NFA to recognize digits """ +def get_digits_enfa() -> Tuple[EpsilonNFA, List[Symbol], + Symbol, Symbol, Symbol, Symbol]: + """An epsilon NFA to recognize digits.""" epsilon = Epsilon() plus = Symbol("+") minus = Symbol("-") @@ -574,21 +580,28 @@ def get_digits_enfa(): enfa.add_transition(states[0], plus, states[1]) enfa.add_transition(states[0], minus, states[1]) for digit in digits: - enfa.add_transitions([ - (states[1], digit, states[1]), - (states[1], digit, states[4]), - (states[2], digit, states[3]), - (states[3], digit, states[3])]) - enfa.add_transitions([ - (states[1], point, states[2]), - (states[4], point, states[3]), - (states[3], epsilon, states[5])]) + enfa.add_transitions( + [ + (states[1], digit, states[1]), + (states[1], digit, states[4]), + (states[2], digit, states[3]), + (states[3], digit, states[3]), + ] + ) + enfa.add_transitions( + [ + (states[1], point, states[2]), + (states[4], point, states[3]), + (states[3], epsilon, states[5]), + ] + ) return enfa, digits, epsilon, plus, minus, point -def get_enfa_example0(): - """ Gives an example ENFA - Accepts a*b +def get_enfa_example0() -> EpsilonNFA: + """Gives an example ENFA. + + Accepts a*b. """ enfa0 = EpsilonNFA() state0 = State(0) @@ -604,9 +617,10 @@ def get_enfa_example0(): return enfa0 -def get_enfa_example1(): - """ Gives an example ENFA - Accepts c +def get_enfa_example1() -> EpsilonNFA: + """Gives an example ENFA. + + Accepts c. """ enfa1 = EpsilonNFA() state2 = State(2) @@ -618,23 +632,18 @@ def get_enfa_example1(): return enfa1 -def get_enfa_example2(): - """ Gives an example ENFA - Accepts (ab+)|c +def get_enfa_example2() -> EpsilonNFA: + """Gives an example ENFA. + + Accepts (ab+)|c. """ - enfa = EpsilonNFA(start_states={0, 3}, - final_states={2, 4}) - enfa.add_transitions([ - (0, "a", 1), - (1, "b", 2), - (2, "b", 2), - (3, "c", 4), - ]) + enfa = EpsilonNFA(start_states={0, 3}, final_states={2, 4}) + enfa.add_transitions([(0, "a", 1), (1, "b", 2), (2, "b", 2), (3, "c", 4)]) return enfa -def get_enfa_example0_bis(): - """ A non minimal NFA, equivalent to example0 """ +def get_enfa_example0_bis() -> EpsilonNFA: + """A non minimal NFA, equivalent to example0.""" enfa0 = EpsilonNFA() state3 = State(3) state4 = State(4) @@ -656,8 +665,8 @@ def get_enfa_example0_bis(): return enfa0 -def get_example_non_minimal(): - """ A non minimal example a.a*.b""" +def get_example_non_minimal() -> EpsilonNFA: + """A non minimal example a.a*.b.""" enfa0 = EpsilonNFA() state0 = State(0) state3 = State(3) @@ -683,8 +692,8 @@ def get_example_non_minimal(): return enfa0 -def get_enfa_example_for_word_generation(): - """ ENFA example for the word generation test """ +def get_enfa_example_for_word_generation() -> EpsilonNFA: + """ENFA example for the word generation test.""" enfa = EpsilonNFA() states = [State(x) for x in range(9)] symbol_a = Symbol("a") @@ -694,17 +703,19 @@ def get_enfa_example_for_word_generation(): symbol_e = Symbol("e") symbol_f = Symbol("f") epsilon = Epsilon() - enfa.add_transitions([ - (states[0], symbol_a, states[1]), - (states[0], epsilon, states[2]), - (states[1], symbol_a, states[1]), - (states[2], symbol_b, states[3]), - (states[2], symbol_c, states[3]), - (states[4], symbol_d, states[5]), - (states[5], symbol_e, states[6]), - (states[5], symbol_e, states[7]), - (states[7], symbol_f, states[8]), - ]) + enfa.add_transitions( + [ + (states[0], symbol_a, states[1]), + (states[0], epsilon, states[2]), + (states[1], symbol_a, states[1]), + (states[2], symbol_b, states[3]), + (states[2], symbol_c, states[3]), + (states[4], symbol_d, states[5]), + (states[5], symbol_e, states[6]), + (states[5], symbol_e, states[7]), + (states[7], symbol_f, states[8]), + ] + ) enfa.add_start_state(states[0]) enfa.add_start_state(states[4]) enfa.add_final_state(states[3]) @@ -714,41 +725,45 @@ def get_enfa_example_for_word_generation(): return enfa -def get_cyclic_enfa_example(): - """ ENFA example with a cycle on the path to the final state """ +def get_cyclic_enfa_example() -> EpsilonNFA: + """ENFA example with a cycle on the path to the final state.""" enfa = EpsilonNFA() states = [State(x) for x in range(4)] symbol_a = Symbol("a") symbol_b = Symbol("b") symbol_c = Symbol("c") epsilon = Epsilon() - enfa.add_transitions([ - (states[0], symbol_a, states[1]), - (states[1], symbol_b, states[2]), - (states[2], epsilon, states[1]), - (states[2], symbol_c, states[3]), - ]) + enfa.add_transitions( + [ + (states[0], symbol_a, states[1]), + (states[1], symbol_b, states[2]), + (states[2], epsilon, states[1]), + (states[2], symbol_c, states[3]), + ] + ) enfa.add_start_state(states[0]) enfa.add_final_state(states[3]) return enfa -def get_epsilon_cycle_enfa_example(): - """ ENFA example with an epsilon cycle """ +def get_epsilon_cycle_enfa_example() -> EpsilonNFA: + """ENFA example with an epsilon cycle.""" enfa = EpsilonNFA() states = [State(x) for x in range(4)] symbol_a = Symbol("a") symbol_b = Symbol("b") symbol_c = Symbol("c") epsilon = Epsilon() - enfa.add_transitions([ - (states[0], epsilon, states[0]), - (states[0], symbol_a, states[1]), - (states[1], symbol_b, states[1]), - (states[1], epsilon, states[2]), - (states[2], epsilon, states[1]), - (states[1], symbol_c, states[3]), - ]) + enfa.add_transitions( + [ + (states[0], epsilon, states[0]), + (states[0], symbol_a, states[1]), + (states[1], symbol_b, states[1]), + (states[1], epsilon, states[2]), + (states[2], epsilon, states[1]), + (states[1], symbol_c, states[3]), + ] + ) enfa.add_start_state(states[0]) enfa.add_final_state(states[0]) enfa.add_final_state(states[3]) diff --git a/pyformlang/finite_automaton/tests/test_nondeterministic_finite_automaton.py b/pyformlang/finite_automaton/tests/test_nondeterministic_finite_automaton.py index d3917e3..4d77f6b 100644 --- a/pyformlang/finite_automaton/tests/test_nondeterministic_finite_automaton.py +++ b/pyformlang/finite_automaton/tests/test_nondeterministic_finite_automaton.py @@ -1,6 +1,4 @@ -""" -Tests for nondeterministic finite automata -""" +"""Tests for nondeterministic finite automata.""" import pytest @@ -11,24 +9,20 @@ class TestNondeterministicFiniteAutomaton: - """ - Tests for nondeterministic finite automata - """ + """Tests for nondeterministic finite automata.""" # pylint: disable=missing-function-docstring, protected-access - def test_creation(self): - """ Test the creation of nfa - """ + def test_creation(self) -> None: + """Test the creation of nfa.""" nfa = NondeterministicFiniteAutomaton() assert nfa is not None states = [State(x) for x in range(10)] nfa = NondeterministicFiniteAutomaton(start_states=set(states)) assert nfa is not None - def test_remove_initial(self): - """ Test the remove of initial state - """ + def test_remove_initial(self) -> None: + """Test the remove of initial state.""" nfa = NondeterministicFiniteAutomaton() state0 = State(0) state1 = State(1) @@ -43,9 +37,8 @@ def test_remove_initial(self): assert nfa.remove_start_state(state0) == 1 assert not nfa.accepts([symb_a]) - def test_accepts(self): - """ Tests the acceptance of nfa - """ + def test_accepts(self) -> None: + """Tests the acceptance of nfa.""" nfa = NondeterministicFiniteAutomaton() state0 = State(0) state1 = State(1) @@ -91,8 +84,8 @@ def test_accepts(self): assert not dfa.accepts([]) assert not dfa.accepts([symb_c]) - def test_deterministic(self): - """ Tests the deterministic transformation """ + def test_deterministic(self) -> None: + """Tests the deterministic transformation.""" nfa = NondeterministicFiniteAutomaton() state0 = State("q0") state1 = State("q1") @@ -109,14 +102,14 @@ def test_deterministic(self): assert len(dfa.states) == 3 assert dfa.get_number_transitions() == 6 - def test_epsilon_refused(self): + def test_epsilon_refused(self) -> None: dfa = NondeterministicFiniteAutomaton() state0 = State(0) state1 = State(1) with pytest.raises(InvalidEpsilonTransitionError): dfa.add_transition(state0, Epsilon(), state1) - def test_copy(self): + def test_copy(self) -> None: nfa = get_nfa_example_with_duplicates().copy() assert len(nfa.states) == 9 assert len(nfa.symbols) == 3 @@ -127,7 +120,7 @@ def test_copy(self): assert nfa.accepts([Symbol("b"), Symbol("c")]) assert not nfa.is_deterministic() - def test_word_generation(self): + def test_word_generation(self) -> None: nfa = get_nfa_example_for_word_generation() accepted_words = list(nfa.get_accepted_words()) assert [] in accepted_words @@ -137,14 +130,14 @@ def test_word_generation(self): assert [Symbol("d"), Symbol("e"), Symbol("f")] in accepted_words assert len(accepted_words) == 5 - def test_for_duplicate_generation(self): + def test_for_duplicate_generation(self) -> None: nfa = get_nfa_example_with_duplicates() accepted_words = list(nfa.get_accepted_words()) assert [Symbol("a"), Symbol("c")] in accepted_words assert [Symbol("b"), Symbol("c")] in accepted_words assert len(accepted_words) == 2 - def test_cyclic_word_generation(self): + def test_cyclic_word_generation(self) -> None: nfa = get_cyclic_nfa_example() accepted_words = list(nfa.get_accepted_words(5)) assert ["a", "d", "g"] in accepted_words @@ -154,12 +147,12 @@ def test_cyclic_word_generation(self): assert ["b", "f", "e", "f", "g"] in accepted_words assert len(accepted_words) == 5 - def test_final_state_at_start_generation(self): + def test_final_state_at_start_generation(self) -> None: nfa = get_nfa_example_with_final_state_at_start() accepted_words = list(nfa.get_accepted_words()) assert accepted_words == [[]] - def test_start_state_at_the_end_generation(self): + def test_start_state_at_the_end_generation(self) -> None: nfa = get_nfa_example_with_start_state_at_the_end() accepted_words = list(nfa.get_accepted_words(5)) assert [] in accepted_words @@ -170,84 +163,88 @@ def test_start_state_at_the_end_generation(self): assert len(accepted_words) == 5 -def get_nfa_example_for_word_generation(): - """ - Gets Nondeterministic Finite Automaton \ - example for the word generation test. - """ - nfa = NondeterministicFiniteAutomaton(start_states={0, 4}, - final_states={3, 4, 6, 8}) - nfa.add_transitions([ - (0, "a", 1), - (0, "a", 2), - (1, "a", 1), - (2, "b", 3), - (2, "c", 3), - (4, "d", 5), - (5, "e", 6), - (5, "e", 7), - (7, "f", 8), - ]) +def get_nfa_example_for_word_generation() -> NondeterministicFiniteAutomaton: + """Gets NFA example for the word generation test.""" + nfa = NondeterministicFiniteAutomaton( + start_states={0, 4}, final_states={3, 4, 6, 8} + ) + nfa.add_transitions( + [ + (0, "a", 1), + (0, "a", 2), + (1, "a", 1), + (2, "b", 3), + (2, "c", 3), + (4, "d", 5), + (5, "e", 6), + (5, "e", 7), + (7, "f", 8), + ] + ) return nfa -def get_nfa_example_with_duplicates(): - """ Gets NFA example with duplicate word chains """ - nfa = NondeterministicFiniteAutomaton(start_states={0, 1, 5, 6}, - final_states={3, 4, 8}) - nfa.add_transitions([ - (0, "a", 2), - (1, "a", 2), - (2, "c", 3), - (2, "c", 4), - (5, "a", 7), - (6, "b", 7), - (7, "c", 8), - ]) +def get_nfa_example_with_duplicates() -> NondeterministicFiniteAutomaton: + """Gets NFA example with duplicate word chains.""" + nfa = NondeterministicFiniteAutomaton( + start_states={0, 1, 5, 6}, final_states={3, 4, 8} + ) + nfa.add_transitions( + [ + (0, "a", 2), + (1, "a", 2), + (2, "c", 3), + (2, "c", 4), + (5, "a", 7), + (6, "b", 7), + (7, "c", 8), + ] + ) return nfa -def get_cyclic_nfa_example(): - """ Gets NFA example with several cycles on path to final """ - nfa = NondeterministicFiniteAutomaton(start_states={0, 5}, - final_states={4}) - nfa.add_transitions([ - (0, "a", 1), - (1, "b", 2), - (2, "c", 1), - (1, "d", 3), - (3, "e", 6), - (6, "f", 3), - (3, "g", 4), - (5, "b", 6), - ]) +def get_cyclic_nfa_example() -> NondeterministicFiniteAutomaton: + """Gets NFA example with several cycles on path to final.""" + nfa = NondeterministicFiniteAutomaton(start_states={0, 5}, final_states={4}) + nfa.add_transitions( + [ + (0, "a", 1), + (1, "b", 2), + (2, "c", 1), + (1, "d", 3), + (3, "e", 6), + (6, "f", 3), + (3, "g", 4), + (5, "b", 6), + ] + ) return nfa -def get_nfa_example_with_final_state_at_start(): - """ Gets NFA example with final state at start """ - nfa = NondeterministicFiniteAutomaton(start_states={0, 5}, - final_states={0}) - nfa.add_transitions([ - (0, "a", 1), - (1, "b", 2), - (2, "c", 3), - (2, "d", 4), - (5, "e", 1), - (5, "e", 2), - ]) +def get_nfa_example_with_final_state_at_start() \ + -> NondeterministicFiniteAutomaton: + """Gets NFA example with final state at start.""" + nfa = NondeterministicFiniteAutomaton(start_states={0, 5}, final_states={0}) + nfa.add_transitions( + [ + (0, "a", 1), + (1, "b", 2), + (2, "c", 3), + (2, "d", 4), + (5, "e", 1), + (5, "e", 2), + ] + ) return nfa -def get_nfa_example_with_start_state_at_the_end(): - """ Gets NFA example with start state at the end """ - nfa = NondeterministicFiniteAutomaton(start_states={0, 3, 4}, - final_states={3}) - nfa.add_transitions([ - (0, "a", 1), - (1, "b", 2), - (2, "e", 1), - (2, "c", 3), - (4, "d", 1), - ]) +def get_nfa_example_with_start_state_at_the_end() \ + -> NondeterministicFiniteAutomaton: + """Gets NFA example with start state at the end.""" + nfa = NondeterministicFiniteAutomaton( + start_states={0, 3, 4}, final_states={3} + ) + nfa.add_transitions( + [(0, "a", 1), (1, "b", 2), (2, "e", 1), (2, "c", 3), (4, "d", 1)] + ) return nfa diff --git a/pyformlang/finite_automaton/tests/test_nondeterministic_transition_function.py b/pyformlang/finite_automaton/tests/test_nondeterministic_transition_function.py index b74440a..0ff4283 100644 --- a/pyformlang/finite_automaton/tests/test_nondeterministic_transition_function.py +++ b/pyformlang/finite_automaton/tests/test_nondeterministic_transition_function.py @@ -1,24 +1,19 @@ -""" -Test the nondeterministic transition functions -""" +"""Test the nondeterministic transition functions.""" from pyformlang.finite_automaton import NondeterministicTransitionFunction from pyformlang.finite_automaton import State, Symbol, Epsilon class TestNondeterministicTransitionFunction: - """ Tests the nondeterministic transitions functions - """ + """Tests the nondeterministic transitions functions.""" - def test_creation(self): - """ Tests the creation of nondeterministic transition functions - """ + def test_creation(self) -> None: + """Tests the creation of nondeterministic transition functions.""" transition_function = NondeterministicTransitionFunction() assert transition_function is not None - def test_add_transitions(self): - """ Tests the addition of transitions - """ + def test_add_transitions(self) -> None: + """Tests the addition of transitions.""" transition_function = NondeterministicTransitionFunction() s_from = State(0) s_to = State(1) @@ -30,9 +25,8 @@ def test_add_transitions(self): transition_function.add_transition(s_to, symb_by, s_to) assert transition_function.get_number_transitions() == 3 - def test_number_transitions(self): - """ Tests the number of transitions - """ + def test_number_transitions(self) -> None: + """Tests the number of transitions.""" transition_function = NondeterministicTransitionFunction() assert transition_function.get_number_transitions() == 0 s_from = State(0) @@ -51,34 +45,26 @@ def test_number_transitions(self): transition_function.add_transition(s_from, symb_by, s_from) assert transition_function.get_number_transitions() == 4 - def test_remove_transitions(self): - """ Tests the removal of transitions - """ + def test_remove_transitions(self) -> None: + """Tests the removal of transitions.""" transition_function = NondeterministicTransitionFunction() s_from = State(0) s_to = State(1) symb_by = Symbol("a") transition_function.add_transition(s_from, symb_by, s_to) - assert transition_function.remove_transition(s_from, - symb_by, - s_to) == 1 + assert transition_function.remove_transition(s_from, symb_by, s_to) == 1 assert len(transition_function(s_to, symb_by)) == 0 assert transition_function.get_number_transitions() == 0 assert len(transition_function(s_from, symb_by)) == 0 - assert transition_function.remove_transition(s_from, - symb_by, - s_to) == 0 + assert transition_function.remove_transition(s_from, symb_by, s_to) == 0 transition_function.add_transition(s_from, symb_by, s_to) transition_function.add_transition(s_from, symb_by, s_from) - assert transition_function.remove_transition(s_from, - symb_by, - s_to) == 1 + assert transition_function.remove_transition(s_from, symb_by, s_to) == 1 assert transition_function.get_number_transitions() == 1 assert len(transition_function(s_from, symb_by)) == 1 - def test_call(self): - """ Tests the call of a transition function - """ + def test_call(self) -> None: + """Tests the call of a transition function.""" transition_function = NondeterministicTransitionFunction() s_from = State(0) s_to = State(1) @@ -89,8 +75,8 @@ def test_call(self): transition_function.add_transition(s_from, symb_by, s_from) assert transition_function(s_from, symb_by) == {s_to, s_from} - def test_get_transitions_from(self): - """ Tests iteration of transitions from specified state """ + def test_get_transitions_from(self) -> None: + """Tests iteration of transitions from specified state.""" transition_function = NondeterministicTransitionFunction() states = [State(x) for x in range(0, 5)] symbol_a = Symbol("a") diff --git a/pyformlang/finite_automaton/tests/test_state.py b/pyformlang/finite_automaton/tests/test_state.py index 6305e50..a8eb013 100644 --- a/pyformlang/finite_automaton/tests/test_state.py +++ b/pyformlang/finite_automaton/tests/test_state.py @@ -1,32 +1,26 @@ -""" -Tests the states -""" +"""Tests the states.""" from pyformlang.finite_automaton import State class TestState: - """ Test the states - """ + """Test the states.""" - def test_can_create(self): - """ Tests the creation of states - """ + def test_can_create(self) -> None: + """Tests the creation of states.""" assert State("") is not None assert State(1) is not None - def test_repr(self): - """ Tests the representation of states - """ + def test_repr(self) -> None: + """Tests the representation of states.""" state1 = State("ABC") assert str(state1) == "ABC" state2 = State(1) assert str(state2) == "1" assert repr(state1) == "State(ABC)" - def test_eq(self): - """ Tests the equality of states - """ + def test_eq(self) -> None: + """Tests the equality of states.""" state1 = State("ABC") state2 = State(1) state3 = State("ABC") @@ -37,9 +31,8 @@ def test_eq(self): assert state1 != state2 assert State("ABC") == "ABC" - def test_hash(self): - """ Tests the hashing of states - """ + def test_hash(self) -> None: + """Tests the hashing of states.""" state1 = hash(State("ABC")) state2 = hash(State(1)) state3 = hash(State("ABC")) diff --git a/pyformlang/finite_automaton/tests/test_symbol.py b/pyformlang/finite_automaton/tests/test_symbol.py index 51e666b..98e2d2c 100644 --- a/pyformlang/finite_automaton/tests/test_symbol.py +++ b/pyformlang/finite_automaton/tests/test_symbol.py @@ -1,32 +1,26 @@ -""" -Tests for the symbols -""" +"""Tests for the symbols.""" from pyformlang.finite_automaton import State, Symbol class TestSymbol: - """ Tests for the symbols - """ + """Tests for the symbols.""" - def test_can_create(self): - """ Tests the creation of symbols - """ + def test_can_create(self) -> None: + """Tests the creation of symbols.""" assert Symbol("") is not None assert Symbol(1) is not None - def test_repr(self): - """ Tests the representation of symbols - """ + def test_repr(self) -> None: + """Tests the representation of symbols.""" symbol1 = Symbol("ABC") assert str(symbol1) == "ABC" symbol2 = Symbol(1) assert str(symbol2) == "1" assert repr(symbol2) == "Symbol(1)" - def test_eq(self): - """ Tests equality of symbols - """ + def test_eq(self) -> None: + """Tests equality of symbols.""" symbol1 = Symbol("ABC") symbol2 = Symbol(1) symbol3 = Symbol("ABC") @@ -37,9 +31,8 @@ def test_eq(self): assert "A" == Symbol("A") assert State("A") != Symbol("A") - def test_hash(self): - """ Tests the hashing of symbols - """ + def test_hash(self) -> None: + """Tests the hashing of symbols.""" symbol1 = hash(Symbol("ABC")) symbol2 = hash(Symbol(1)) symbol3 = hash(Symbol("ABC")) diff --git a/pyformlang/fst/tests/test_fst.py b/pyformlang/fst/tests/test_fst.py index 7914389..578ba49 100644 --- a/pyformlang/fst/tests/test_fst.py +++ b/pyformlang/fst/tests/test_fst.py @@ -1,4 +1,5 @@ -""" Tests the FST """ +"""Tests the FST.""" + # pylint: disable=duplicate-code from os import path @@ -8,27 +9,28 @@ @pytest.fixture -def fst0(): - fst0 = FST() - fst0.add_start_state("q0") - fst0.add_transition("q0", "a", "q1", ["b"]) - fst0.add_final_state("q1") - yield fst0 +def fst0() -> FST: + fst = FST() + fst.add_start_state("q0") + fst.add_transition("q0", "a", "q1", ["b"]) + fst.add_final_state("q1") + return fst @pytest.fixture -def fst1(): - fst1 = FST() - fst1.add_start_state("q1") - fst1.add_transition("q1", "b", "q2", ["c"]) - fst1.add_final_state("q2") - yield fst1 +def fst1() -> FST: + fst = FST() + fst.add_start_state("q1") + fst.add_transition("q1", "b", "q2", ["c"]) + fst.add_final_state("q2") + return fst class TestFST: - """ Tests FST """ - def test_creation(self): - """ Test Translate """ + """Tests FST.""" + + def test_creation(self) -> None: + """Test Translate.""" fst = FST() assert fst is not None assert len(fst.states) == 0 @@ -68,8 +70,8 @@ def test_creation(self): assert fst.get_number_transitions() == 3 assert len(fst.final_states) == 1 - def test_translate(self): - """ Test a translation """ + def test_translate(self) -> None: + """Test a translation.""" fst = FST() fst.add_start_state("q0") translation = list(fst.translate(["a"])) @@ -91,14 +93,14 @@ def test_translate(self): assert ["b", "c"] in translation assert ["b"] + ["c"] * 9 in translation - def test_union(self, fst0, fst1): - """ Tests the union""" + def test_union(self, fst0: FST, fst1: FST) -> None: + """Tests the union.""" fst_union = fst0.union(fst1) self._make_test_fst_union(fst_union) fst_union = fst0 | fst1 self._make_test_fst_union(fst_union) - def _make_test_fst_union(self, fst_union): + def _make_test_fst_union(self, fst_union: FST) -> None: assert len(fst_union.start_states) == 2 assert len(fst_union.final_states) == 2 assert fst_union.get_number_transitions() == 2 @@ -109,8 +111,8 @@ def _make_test_fst_union(self, fst_union): translation = list(fst_union.translate(["a", "b"])) assert translation == [] - def test_concatenate(self, fst0, fst1): - """ Tests the concatenation """ + def test_concatenate(self, fst0: FST, fst1: FST) -> None: + """Tests the concatenation.""" fst_concatenate = fst0 + fst1 translation = list(fst_concatenate.translate(["a", "b"])) assert translation == [["b", "c"]] @@ -119,8 +121,8 @@ def test_concatenate(self, fst0, fst1): translation = list(fst_concatenate.translate(["b"])) assert translation == [] - def test_concatenate2(self, fst0, fst1): - """ Tests the concatenation """ + def test_concatenate2(self, fst0: FST, fst1: FST) -> None: + """Tests the concatenation.""" fst_concatenate = fst0 + fst1 + fst1 translation = list(fst_concatenate.translate(["a", "b", "b"])) assert translation == [["b", "c", "c"]] @@ -129,8 +131,8 @@ def test_concatenate2(self, fst0, fst1): translation = list(fst_concatenate.translate(["b"])) assert translation == [] - def test_kleene_start(self, fst0): - """ Tests the kleene star on a fst""" + def test_kleene_start(self, fst0: FST) -> None: + """Tests the kleene star on a fst.""" fst_star = fst0.kleene_star() translation = list(fst_star.translate(["a"])) assert translation == [["b"]] @@ -139,8 +141,8 @@ def test_kleene_start(self, fst0): translation = list(fst_star.translate([])) assert translation == [[]] - def test_generate_empty_word_from_nothing(self): - """ Generate empty word from nothing """ + def test_generate_empty_word_from_nothing(self) -> None: + """Generate empty word from nothing.""" fst = FST() fst.add_start_state("q0") fst.add_transition("q0", "epsilon", "q1", []) @@ -148,8 +150,8 @@ def test_generate_empty_word_from_nothing(self): translation = list(fst.translate([])) assert translation == [[]] - def test_epsilon_loop(self): - """ Test empty loop """ + def test_epsilon_loop(self) -> None: + """Test empty loop.""" fst = FST() fst.add_start_state("q0") fst.add_transition("q0", "epsilon", "q1", []) @@ -158,48 +160,55 @@ def test_epsilon_loop(self): translation = list(fst.translate([])) assert translation == [[]] - def test_epsilon_loop2(self): - """ Test empty loop bis """ + def test_epsilon_loop2(self) -> None: + """Test empty loop bis.""" fst = FST() fst.add_start_state("q0") fst.add_transitions( - [("q0", "epsilon", "q1", []), - ("q1", "a", "q2", ["b"]), - ("q1", "epsilon", "q0", [])]) + [ + ("q0", "epsilon", "q1", []), + ("q1", "a", "q2", ["b"]), + ("q1", "epsilon", "q0", []), + ] + ) fst.add_final_state("q2") translation = list(fst.translate(["a"])) assert translation == [["b"]] - def test_paper(self): - """ Test for the paper """ + def test_paper(self) -> None: + """Test for the paper.""" fst = FST() fst.add_transitions( - [(0, "I", 1, ["Je"]), (1, "am", 2, ["suis"]), - (2, "alone", 3, ["tout", "seul"]), - (2, "alone", 3, ["seul"])]) + [ + (0, "I", 1, ["Je"]), + (1, "am", 2, ["suis"]), + (2, "alone", 3, ["tout", "seul"]), + (2, "alone", 3, ["seul"]), + ] + ) fst.add_start_state(0) fst.add_final_state(3) translation = list(fst.translate(["I", "am", "alone"])) - assert ['Je', 'suis', 'seul'] in translation - assert ['Je', 'suis', 'tout', 'seul'] in translation + assert ["Je", "suis", "seul"] in translation + assert ["Je", "suis", "tout", "seul"] in translation assert len(translation) == 2 fst = FST.from_networkx(fst.to_networkx()) translation = list(fst.translate(["I", "am", "alone"])) - assert ['Je', 'suis', 'seul'] in translation - assert ['Je', 'suis', 'tout', 'seul'] in translation + assert ["Je", "suis", "seul"] in translation + assert ["Je", "suis", "tout", "seul"] in translation assert len(translation) == 2 fst.write_as_dot("fst.dot") assert path.exists("fst.dot") - def test_contains(self, fst0: FST): - """ Tests the containment of transition in the FST """ + def test_contains(self, fst0: FST) -> None: + """Tests the containment of transition in the FST.""" assert ("q0", "a", "q1", ["b"]) in fst0 assert ("a", "b", "c", ["d"]) not in fst0 fst0.add_transition("a", "b", "c", {"d"}) assert ("a", "b", "c", ["d"]) in fst0 - def test_iter(self, fst0: FST): - """ Tests the iteration of FST transitions """ + def test_iter(self, fst0: FST) -> None: + """Tests the iteration of FST transitions.""" fst0.add_transition("q1", "A", "q2", ["B"]) fst0.add_transition("q1", "A", "q2", ["C", "D"]) transitions = list(iter(fst0)) @@ -208,8 +217,8 @@ def test_iter(self, fst0: FST): assert (("q1", "A"), ("q2", ("C", "D"))) in transitions assert len(transitions) == 3 - def test_remove_transition(self, fst0: FST): - """ Tests the removal of transition from the FST """ + def test_remove_transition(self, fst0: FST) -> None: + """Tests the removal of transition from the FST.""" assert ("q0", "a", "q1", ["b"]) in fst0 fst0.remove_transition("q0", "a", "q1", ["b"]) assert ("q0", "a", "q1", ["b"]) not in fst0 @@ -217,13 +226,15 @@ def test_remove_transition(self, fst0: FST): assert ("q0", "a", "q1", ["b"]) not in fst0 assert fst0.get_number_transitions() == 0 - def test_initialization(self): - """ Tests the initialization of the FST """ - fst = FST(states={0}, - input_symbols={"a", "b"}, - output_symbols={"c"}, - start_states={1}, - final_states={2}) + def test_initialization(self) -> None: + """Tests the initialization of the FST.""" + fst = FST( + states={0}, + input_symbols={"a", "b"}, + output_symbols={"c"}, + start_states={1}, + final_states={2}, + ) assert fst.states == {0, 1, 2} assert fst.input_symbols == {"a", "b"} assert fst.output_symbols == {"c"} @@ -239,8 +250,8 @@ def test_initialization(self): assert (1, "a", 2, ["c"]) in fst assert fst(1, "a") == {(2, tuple("b")), (2, tuple("c"))} - def test_copy(self, fst0: FST): - """ Tests the copying of the FST """ + def test_copy(self, fst0: FST) -> None: + """Tests the copying of the FST.""" fst_copy = fst0.copy() assert fst_copy.states == fst0.states assert fst_copy.input_symbols == fst0.input_symbols diff --git a/pyformlang/indexed_grammar/tests/test_indexed_grammar.py b/pyformlang/indexed_grammar/tests/test_indexed_grammar.py index 6f4bb01..29d9be2 100644 --- a/pyformlang/indexed_grammar/tests/test_indexed_grammar.py +++ b/pyformlang/indexed_grammar/tests/test_indexed_grammar.py @@ -1,7 +1,8 @@ -""" -Testing of indexed grammar, with manual rules -""" -from pyformlang.indexed_grammar import Rules +"""Testing of indexed grammar, with manual rules.""" + +from typing import Iterable + +from pyformlang.indexed_grammar import Rules, ReducedRule from pyformlang.indexed_grammar import ConsumptionRule from pyformlang.indexed_grammar import EndRule from pyformlang.indexed_grammar import ProductionRule @@ -12,13 +13,12 @@ class TestIndexedGrammar: - """ Tests the indexed grammar """ + """Tests the indexed grammar.""" # pylint: disable=missing-function-docstring - def test_simple_ig_0(self): - """Test""" - + def test_simple_ig_0(self) -> None: + """Test.""" l_rules = get_example_rules() for i in range(9): @@ -27,7 +27,7 @@ def test_simple_ig_0(self): assert not i_grammar.is_empty() assert i_grammar.terminals == {"end", "b", "epsilon"} - def test_simple_ig_1(self): + def test_simple_ig_1(self) -> None: # Write rules l_rules = [ @@ -55,13 +55,14 @@ def test_simple_ig_1(self): DuplicationRule("E1", "F1", "E2"), EndRule("E2", "epsilon"), EndRule("F0", "c"), - EndRule("F1", "b")] + EndRule("F1", "b"), + ] rules = Rules(l_rules) i_grammar = IndexedGrammar(rules) assert not i_grammar.is_empty() - def test_simple_ig_2(self): + def test_simple_ig_2(self) -> None: # Write rules l_rules = [ @@ -85,13 +86,14 @@ def test_simple_ig_2(self): DuplicationRule("E1", "F1", "E2"), EndRule("E2", "epsilon"), EndRule("F0", "c"), - EndRule("F1", "b")] + EndRule("F1", "b"), + ] rules = Rules(l_rules) i_grammar = IndexedGrammar(rules) assert i_grammar.is_empty() - def test_simple_ig_3(self): + def test_simple_ig_3(self) -> None: # Write rules l_rules = [] @@ -113,7 +115,7 @@ def test_simple_ig_3(self): i_grammar = IndexedGrammar(rules) assert i_grammar.is_empty() - def test_simple_ig_4(self): + def test_simple_ig_4(self) -> None: # Write rules l_rules = [] @@ -152,7 +154,7 @@ def test_simple_ig_4(self): i_grammar = IndexedGrammar(rules) assert i_grammar.is_empty() - def test_simple_ig_5(self): + def test_simple_ig_5(self) -> None: # Write rules l_rules = [] @@ -171,7 +173,7 @@ def test_simple_ig_5(self): i_grammar = IndexedGrammar(rules) assert not i_grammar.is_empty() - def test_simple_ig_regular_expression(self): + def test_simple_ig_regular_expression(self) -> None: # Test for regular expression functions l_rules = [] @@ -193,8 +195,8 @@ def test_simple_ig_regular_expression(self): i_grammar = IndexedGrammar(rules) assert not i_grammar.is_empty() - def test_simple_ig6(self): - """ Test number 6 """ + def test_simple_ig6(self) -> None: + """Test number 6.""" l_rules = [] l_rules.append(DuplicationRule("S", "S", "B")) rules = Rules(l_rules) @@ -215,8 +217,8 @@ def test_simple_ig6(self): i_grammar = IndexedGrammar(rules) assert not i_grammar.is_empty() - def test_simple_ig7(self): - """ Test 7 """ + def test_simple_ig7(self) -> None: + """Test 7.""" l_rules = [] l_rules.append(ProductionRule("S", "A", "end")) l_rules.append(ConsumptionRule("end", "A", "S")) @@ -227,8 +229,8 @@ def test_simple_ig7(self): i_grammar = IndexedGrammar(rules) assert not i_grammar.is_empty() - def test_simple_ig8(self): - """ Tests 8 """ + def test_simple_ig8(self) -> None: + """Tests 8.""" l_rules = [] l_rules.append(ProductionRule("S", "Q", "end")) l_rules.append(ProductionRule("Q", "A", "end")) @@ -243,8 +245,8 @@ def test_simple_ig8(self): i_grammar = IndexedGrammar(rules) assert not i_grammar.is_empty() - def test_simple_ig9(self): - """ Tests 9 {a^n b^n c^n}""" + def test_simple_ig9(self) -> None: + """Tests 9 {a^n b^n c^n}.""" l_rules = [] l_rules.append(ProductionRule("S", "T", "g")) l_rules.append(ProductionRule("T", "T", "f")) @@ -266,8 +268,8 @@ def test_simple_ig9(self): i_grammar = IndexedGrammar(rules) assert not i_grammar.is_empty() - def test_start_symbol(self): - """ Tests the change of the start symbol """ + def test_start_symbol(self) -> None: + """Tests the change of the start symbol.""" l_rules = [] l_rules.append(EndRule("S", "s")) rules = Rules(l_rules) @@ -283,8 +285,8 @@ def test_start_symbol(self): i_grammar = IndexedGrammar(rules, start_variable="S2") assert not i_grammar.is_empty() - def test_reachable(self): - """ Tests the reachable symbols """ + def test_reachable(self) -> None: + """Tests the reachable symbols.""" l_rules = [] l_rules.append(DuplicationRule("S", "A", "B")) l_rules.append(ProductionRule("A", "D", "f")) @@ -300,8 +302,8 @@ def test_reachable(self): reachable = i_grammar.get_reachable_non_terminals() assert reachable == {"S", "A", "B", "D", "G"} - def test_generating(self): - """ Tests the generating symbols """ + def test_generating(self) -> None: + """Tests the generating symbols.""" l_rules = [] l_rules.append(DuplicationRule("S", "A", "B")) l_rules.append(ProductionRule("A", "D", "f")) @@ -317,8 +319,8 @@ def test_generating(self): generating = i_grammar.get_generating_non_terminals() assert generating == {"D", "A", "E", "Q"} - def test_removal_useless(self): - """ Tests the removal of useless symbols """ + def test_removal_useless(self) -> None: + """Tests the removal of useless symbols.""" l_rules = [] l_rules.append(ProductionRule("S", "D", "f")) @@ -334,28 +336,35 @@ def test_removal_useless(self): i_grammar = IndexedGrammar(rules, start_variable="S") i_grammar2 = i_grammar.remove_useless_rules() assert not i_grammar.is_empty() - assert i_grammar2.non_terminals == \ - i_grammar2.get_generating_non_terminals() - assert i_grammar2.non_terminals == \ - i_grammar2.get_reachable_non_terminals() + assert ( + i_grammar2.non_terminals + == i_grammar2.get_generating_non_terminals() + ) + assert ( + i_grammar2.non_terminals == i_grammar2.get_reachable_non_terminals() + ) + + def test_intersection0(self) -> None: + """Tests the intersection of indexed grammar with regex. - def test_intersection0(self): - """ Tests the intersection of indexed grammar with regex Long to run! """ - l_rules = [ProductionRule("S", "D", "f"), - DuplicationRule("D", "A", "B"), - ConsumptionRule("f", "A", "Afinal"), - ConsumptionRule("f", "B", "Bfinal"), EndRule("Afinal", "a"), - EndRule("Bfinal", "b")] + l_rules = [ + ProductionRule("S", "D", "f"), + DuplicationRule("D", "A", "B"), + ConsumptionRule("f", "A", "Afinal"), + ConsumptionRule("f", "B", "Bfinal"), + EndRule("Afinal", "a"), + EndRule("Bfinal", "b"), + ] rules = Rules(l_rules, 6) indexed_grammar = IndexedGrammar(rules) fst = Regex("a.b").to_epsilon_nfa().to_fst() i_inter = indexed_grammar.intersection(fst) assert i_inter - def test_intersection1(self): - """ Test the intersection with fst """ + def test_intersection1(self) -> None: + """Test the intersection with fst.""" l_rules = [] rules = Rules(l_rules) indexed_grammar = IndexedGrammar(rules) @@ -383,8 +392,8 @@ def test_intersection1(self): assert not intersection.is_empty() -def get_example_rules(): - """ Duplicate example of rules """ +def get_example_rules() -> Iterable[ReducedRule]: + """Duplicate example of rules.""" l_rules = [ # Initialization rules ProductionRule("S", "Cinit", "end"), ProductionRule("Cinit", "C", "b"), @@ -393,6 +402,7 @@ def get_example_rules(): # C[cm sigma] -> cm C[sigma] ConsumptionRule("b", "C", "B0"), DuplicationRule("B0", "A0", "C"), - EndRule("A0", "b")] + EndRule("A0", "b"), + ] return l_rules diff --git a/pyformlang/indexed_grammar/tests/test_rules.py b/pyformlang/indexed_grammar/tests/test_rules.py index e0b3ce7..3f00bf8 100644 --- a/pyformlang/indexed_grammar/tests/test_rules.py +++ b/pyformlang/indexed_grammar/tests/test_rules.py @@ -1,49 +1,49 @@ -""" -Testing the rules -""" +"""Testing the rules.""" + from pyformlang.indexed_grammar import ProductionRule from pyformlang.indexed_grammar import DuplicationRule from pyformlang.indexed_grammar import Rules from pyformlang.indexed_grammar import ConsumptionRule from pyformlang.indexed_grammar import EndRule -from pyformlang.indexed_grammar.tests.test_indexed_grammar \ - import get_example_rules +from pyformlang.indexed_grammar.tests.test_indexed_grammar import ( + get_example_rules, +) class TestIndexedGrammar: - """ Tests things related to rules """ + """Tests things related to rules.""" # pylint: disable=missing-function-docstring - def test_consumption_rules(self): - """ Tests the consumption rules """ + def test_consumption_rules(self) -> None: + """Tests the consumption rules.""" consumption = ConsumptionRule("end", "C", "T") terminals = consumption.terminals assert terminals == {"end"} representation = str(consumption) assert representation == "C [ end ] -> T" - def test_duplication_rules(self): - """ Tests the duplication rules """ + def test_duplication_rules(self) -> None: + """Tests the duplication rules.""" duplication = DuplicationRule("B0", "A0", "C") assert duplication.terminals == set() assert str(duplication) == "B0 -> A0 C" - def test_end_rule(self): - """ Tests the end rules """ + def test_end_rule(self) -> None: + """Tests the end rules.""" end_rule = EndRule("A0", "b") assert end_rule.terminals == {"b"} assert end_rule.right_term == "b" assert str(end_rule) == "A0 -> b" - def test_production_rules(self): - """ Tests the production rules """ + def test_production_rules(self) -> None: + """Tests the production rules.""" production = ProductionRule("S", "C", "end") assert production.terminals == {"end"} assert str(production) == "S -> C [ end ]" - def test_rules(self): - """ Tests the rules """ + def test_rules(self) -> None: + """Tests the rules.""" l_rules = get_example_rules() rules = Rules(l_rules) assert rules.terminals == {"b", "end", "epsilon"} diff --git a/pyformlang/pda/tests/test_pda.py b/pyformlang/pda/tests/test_pda.py index 5399041..6e5f919 100644 --- a/pyformlang/pda/tests/test_pda.py +++ b/pyformlang/pda/tests/test_pda.py @@ -1,8 +1,9 @@ -""" Tests the PDA """ +"""Tests the PDA.""" -import pytest from os import path +import pytest + from pyformlang.pda import PDA, State, StackSymbol, Symbol, Epsilon from pyformlang.cfg import Terminal, Epsilon as CFGEpsilon from pyformlang.finite_automaton import DeterministicFiniteAutomaton @@ -13,11 +14,13 @@ @pytest.fixture def pda_example() -> PDA: pda = PDA() - pda.add_transitions([ - ("q0", "0", "Z0", "q1", ("Z1", "Z0")), - ("q1", "1", "Z1", "q2", []), - ("q0", "epsilon", "Z1", "q2", []) - ]) + pda.add_transitions( + [ + ("q0", "0", "Z0", "q1", ("Z1", "Z0")), + ("q1", "1", "Z1", "q2", []), + ("q0", "epsilon", "Z1", "q2", []), + ] + ) pda.set_start_state("q0") pda.set_start_stack_symbol("Z0") pda.add_final_state("q2") @@ -25,10 +28,10 @@ def pda_example() -> PDA: class TestPDA: - """ Tests the pushdown automata """ + """Tests the pushdown automata.""" - def test_creation(self): - """ Test of creation """ + def test_creation(self) -> None: + """Test of creation.""" pda = PDA() assert pda is not None assert len(pda.states) == 0 @@ -43,16 +46,18 @@ def test_creation(self): assert len(pda.stack_symbols) == 0 assert len(pda.final_states) == 0 - pda = PDA(final_states={State("A"), State("A"), State("B"), - Symbol("B")}) + pda = PDA( + final_states={State("A"), State("A"), State("B"), Symbol("B")} + ) assert pda is not None assert len(pda.states) == 2 assert len(pda.input_symbols) == 0 assert len(pda.stack_symbols) == 0 assert len(pda.final_states) == 2 - pda = PDA(input_symbols={Symbol("A"), Symbol("B"), - Symbol("A"), State("A")}) + pda = PDA( + input_symbols={Symbol("A"), Symbol("B"), Symbol("A"), State("A")} + ) assert pda is not None assert len(pda.states) == 0 assert len(pda.input_symbols) == 2 @@ -66,8 +71,14 @@ def test_creation(self): assert len(pda.stack_symbols) == 1 assert len(pda.final_states) == 0 - pda = PDA(stack_alphabet={StackSymbol("A"), StackSymbol("A"), - StackSymbol("B"), Symbol("B")}) + pda = PDA( + stack_alphabet={ + StackSymbol("A"), + StackSymbol("A"), + StackSymbol("B"), + Symbol("B"), + } + ) assert pda is not None assert len(pda.states) == 0 assert len(pda.input_symbols) == 0 @@ -82,8 +93,8 @@ def test_creation(self): assert pda.get_number_transitions() == 0 assert len(pda.final_states) == 0 - def test_represent(self): - """ Tests representations """ + def test_represent(self) -> None: + """Tests representations.""" symb = Symbol("S") assert repr(symb) == "Symbol(S)" state = State("T") @@ -96,30 +107,34 @@ def test_represent(self): assert str(StackSymbol(12)) == "12" assert repr(StackSymbol(12)) == "StackSymbol(12)" - def test_transition(self): - """ Tests the creation of transition """ + def test_transition(self) -> None: + """Tests the creation of transition.""" pda = PDA() - pda.add_transition(State("from"), - Symbol("input symbol"), - StackSymbol("stack symbol"), - State("to"), - [StackSymbol("A"), StackSymbol("B")]) + pda.add_transition( + State("from"), + Symbol("input symbol"), + StackSymbol("stack symbol"), + State("to"), + [StackSymbol("A"), StackSymbol("B")], + ) assert len(pda.states) == 2 assert len(pda.input_symbols) == 1 assert len(pda.stack_symbols) == 3 assert pda.get_number_transitions() == 1 - pda.add_transition(State("from"), - Epsilon(), - StackSymbol("stack symbol"), - State("to"), - [StackSymbol("A"), StackSymbol("B")]) + pda.add_transition( + State("from"), + Epsilon(), + StackSymbol("stack symbol"), + State("to"), + [StackSymbol("A"), StackSymbol("B")], + ) assert len(pda.states) == 2 assert len(pda.input_symbols) == 1 assert len(pda.stack_symbols) == 3 assert pda.get_number_transitions() == 2 - def test_example62(self): - """ Example from the book """ + def test_example62(self) -> None: + """Example from the book.""" state0 = State("q0") state1 = State("q1") state2 = State("q2") @@ -128,12 +143,14 @@ def test_example62(self): ss_zero = StackSymbol("0") ss_one = StackSymbol("1") ss_z0 = StackSymbol("Z0") - pda = PDA(states={state0, state1, state2}, - input_symbols={s_zero, s_one}, - stack_alphabet={ss_zero, ss_one, ss_z0}, - start_state=state0, - start_stack_symbol=ss_z0, - final_states={state2}) + pda = PDA( + states={state0, state1, state2}, + input_symbols={s_zero, s_one}, + stack_alphabet={ss_zero, ss_one, ss_z0}, + start_state=state0, + start_stack_symbol=ss_z0, + final_states={state2}, + ) assert len(pda.states) == 3 assert len(pda.input_symbols) == 2 assert len(pda.stack_symbols) == 3 @@ -167,22 +184,22 @@ def test_example62(self): assert not cfg.contains([t_zero]) assert not cfg.contains([t_zero, t_one, t_zero]) - def test_to_final_state(self): - """ Test transformation to final state """ + def test_to_final_state(self) -> None: + """Test transformation to final state.""" state = State("#STARTTOFINAL#") symbol_e = Symbol("e") symbol_i = Symbol("i") symbol_z = StackSymbol("Z") - pda = PDA(states={state}, - input_symbols={symbol_i, symbol_e}, - stack_alphabet={symbol_z}, - start_state=state, - start_stack_symbol=symbol_z) - pda.add_transition(state, - symbol_i, - symbol_z, - state, - [symbol_z, symbol_z]) + pda = PDA( + states={state}, + input_symbols={symbol_i, symbol_e}, + stack_alphabet={symbol_z}, + start_state=state, + start_stack_symbol=symbol_z, + ) + pda.add_transition( + state, symbol_i, symbol_z, state, [symbol_z, symbol_z] + ) pda.add_transition(state, symbol_e, symbol_z, state, []) new_pda = pda.to_final_state() assert len(new_pda.states) == 3 @@ -191,24 +208,28 @@ def test_to_final_state(self): assert new_pda.get_number_transitions() == 4 assert len(new_pda.final_states) == 1 - def test_to_empty_stack(self): - """ Test transformation to empty stack """ + def test_to_empty_stack(self) -> None: + """Test transformation to empty stack.""" state_q = State("#STARTTOFINAL#") state_q0 = State("q0") symbol_e = Symbol("e") symbol_i = Symbol("i") symbol_z = StackSymbol("Z") symbol_z0 = StackSymbol("Z0") - pda = PDA(states={state_q, state_q0}, - input_symbols={symbol_i, symbol_e}, - stack_alphabet={symbol_z, symbol_z0}, - start_state=state_q, - start_stack_symbol=symbol_z0, - final_states={state_q0}) - pda.add_transition(state_q, symbol_i, symbol_z, state_q, - [symbol_z, symbol_z]) - pda.add_transition(state_q, symbol_i, symbol_z0, state_q, - [symbol_z, symbol_z0]) + pda = PDA( + states={state_q, state_q0}, + input_symbols={symbol_i, symbol_e}, + stack_alphabet={symbol_z, symbol_z0}, + start_state=state_q, + start_stack_symbol=symbol_z0, + final_states={state_q0}, + ) + pda.add_transition( + state_q, symbol_i, symbol_z, state_q, [symbol_z, symbol_z] + ) + pda.add_transition( + state_q, symbol_i, symbol_z0, state_q, [symbol_z, symbol_z0] + ) pda.add_transition(state_q, symbol_e, symbol_z, state_q, []) pda.add_transition(state_q, Epsilon(), symbol_z0, state_q0, []) new_pda = pda.to_empty_stack() @@ -218,30 +239,35 @@ def test_to_empty_stack(self): assert new_pda.get_number_transitions() == 11 assert len(new_pda.final_states) == 0 - def test_to_cfg(self): - """ Test the transformation to CFG """ + def test_to_cfg(self) -> None: + """Test the transformation to CFG.""" state_q = State("#STARTTOFINAL#") symbol_e = Symbol("e") symbol_i = Symbol("i") symbol_z = StackSymbol("Z") - pda = PDA(states={state_q}, - input_symbols={symbol_i, symbol_e}, - stack_alphabet={symbol_z}, - start_state=state_q, - start_stack_symbol=symbol_z) - pda.add_transition(state_q, symbol_i, symbol_z, state_q, - [symbol_z, symbol_z]) + pda = PDA( + states={state_q}, + input_symbols={symbol_i, symbol_e}, + stack_alphabet={symbol_z}, + start_state=state_q, + start_stack_symbol=symbol_z, + ) + pda.add_transition( + state_q, symbol_i, symbol_z, state_q, [symbol_z, symbol_z] + ) pda.add_transition(state_q, symbol_e, symbol_z, state_q, []) cfg = pda.to_cfg() assert len(cfg.variables) == 2 assert len(cfg.terminals) == 2 assert len(cfg.productions) == 3 - pda = PDA(states={"q"}, - input_symbols={"i", "e"}, - stack_alphabet={"Z"}, - start_state="q", - start_stack_symbol="Z") + pda = PDA( + states={"q"}, + input_symbols={"i", "e"}, + stack_alphabet={"Z"}, + start_state="q", + start_stack_symbol="Z", + ) pda.add_transition("q", "i", "Z", "q", ("Z", "Z")) pda.add_transition("q", "e", "Z", "q", []) cfg = pda.to_cfg() @@ -250,8 +276,8 @@ def test_to_cfg(self): assert len(cfg.productions) == 3 pda.add_transition("q", "epsilon", "Z", "q", ["Z"]) - def test_pda_conversion(self): - """ Tests conversions from a PDA """ + def test_pda_conversion(self) -> None: + """Tests conversions from a PDA.""" state_p = State("p") state_q = State("q") state_a = Symbol("a") @@ -264,17 +290,27 @@ def test_pda_conversion(self): stack_symbol_b = StackSymbol("b") stack_symbol_c = StackSymbol("c") stack_symbol_x0 = StackSymbol("X0") - pda = PDA(states={state_p, state_q}, - input_symbols={state_a, state_b, state_c}, - stack_alphabet={stack_symbol_a, stack_symbol_b, - stack_symbol_c, stack_symbol_x0}, - start_state=state_p, - start_stack_symbol=stack_symbol_x0, - final_states={state_q}) + pda = PDA( + states={state_p, state_q}, + input_symbols={state_a, state_b, state_c}, + stack_alphabet={ + stack_symbol_a, + stack_symbol_b, + stack_symbol_c, + stack_symbol_x0, + }, + start_state=state_p, + start_stack_symbol=stack_symbol_x0, + final_states={state_q}, + ) pda.add_transition(state_p, Epsilon(), stack_symbol_x0, state_q, []) - pda.add_transition(state_p, Epsilon(), stack_symbol_x0, state_p, - [stack_symbol_a, stack_symbol_b, - stack_symbol_c, stack_symbol_x0]) + pda.add_transition( + state_p, + Epsilon(), + stack_symbol_x0, + state_p, + [stack_symbol_a, stack_symbol_b, stack_symbol_c, stack_symbol_x0], + ) pda.add_transition(state_p, state_a, stack_symbol_a, state_p, []) pda.add_transition(state_p, state_b, stack_symbol_b, state_p, []) pda.add_transition(state_p, state_c, stack_symbol_c, state_p, []) @@ -283,8 +319,8 @@ def test_pda_conversion(self): assert cfg.contains([terminal_a, terminal_b, terminal_c]) assert not cfg.contains([terminal_c, terminal_b, terminal_a]) - def test_intersection_regex(self): - """ Tests the intersection with a regex """ + def test_intersection_regex(self) -> None: + """Tests the intersection with a regex.""" # pylint: disable=too-many-locals state_p = State("p") state_q = State("q") @@ -293,16 +329,20 @@ def test_intersection_regex(self): state_e = Symbol("e") state_z = StackSymbol("Z") state_x0 = StackSymbol("X0") - pda = PDA(states={state_p, state_q, state_r}, - input_symbols={state_i, state_e}, - stack_alphabet={state_z, state_x0}, - start_state=state_p, - start_stack_symbol=state_x0, - final_states={state_r}) - pda.add_transition(state_p, Epsilon(), state_x0, state_q, - [state_z, state_x0]) - pda.add_transition(state_q, state_i, state_z, state_q, - [state_z, state_z]) + pda = PDA( + states={state_p, state_q, state_r}, + input_symbols={state_i, state_e}, + stack_alphabet={state_z, state_x0}, + start_state=state_p, + start_stack_symbol=state_x0, + final_states={state_r}, + ) + pda.add_transition( + state_p, Epsilon(), state_x0, state_q, [state_z, state_x0] + ) + pda.add_transition( + state_q, state_i, state_z, state_q, [state_z, state_z] + ) pda.add_transition(state_q, state_e, state_z, state_q, []) pda.add_transition(state_q, Epsilon(), state_x0, state_r, []) @@ -314,7 +354,8 @@ def test_intersection_regex(self): states={state_s, state_t}, input_symbols={i_dfa, e_dfa}, start_state=state_s, - final_states={state_s, state_t}) + final_states={state_s, state_t}, + ) dfa.add_transition(state_s, i_dfa, state_s) dfa.add_transition(state_s, e_dfa, state_t) dfa.add_transition(state_t, e_dfa, state_t) @@ -346,8 +387,8 @@ def test_intersection_regex(self): cfg = pda_es.to_cfg() assert not cfg - def test_pda_paper(self, pda_example: PDA): - """ Code in the paper """ + def test_pda_paper(self, pda_example: PDA) -> None: + """Code in the paper.""" pda = pda_example pda_final_state = pda.to_final_state() assert pda_final_state is not None @@ -364,8 +405,8 @@ def test_pda_paper(self, pda_example: PDA): assert cfg.contains(["0", "1"]) assert path.exists("pda.dot") - def test_copy(self, pda_example: PDA): - """ Tests the copying of PDA """ + def test_copy(self, pda_example: PDA) -> None: + """Tests the copying of PDA.""" pda = pda_example pda_copy = pda.copy() assert pda.states == pda_copy.states @@ -377,8 +418,8 @@ def test_copy(self, pda_example: PDA): assert pda.final_states == pda_copy.final_states assert pda is not pda_copy - def test_object_eq(self): - """ Tests the equality of pda objects """ + def test_object_eq(self) -> None: + """Tests the equality of pda objects.""" assert StackSymbol("c") == StackSymbol("c") assert State("a") == "a" assert "C" == Symbol("C") @@ -395,8 +436,8 @@ def test_object_eq(self): assert Terminal(1) != StackSymbol(1) assert StackSymbol(42) != FAState(42) - def test_contains(self, pda_example: PDA): - """ Tests the transition containment checks """ + def test_contains(self, pda_example: PDA) -> None: + """Tests the transition containment checks.""" pda = pda_example assert ("q1", "1", "Z1", "q2", []) in pda assert ("q0", "epsilon", "Z1", "q2", tuple()) in pda @@ -404,8 +445,8 @@ def test_contains(self, pda_example: PDA): pda.add_transition("q1", "1", "Z1", "q5", ["a"]) assert ("q1", "1", "Z1", "q5", ["a"]) in pda - def test_remove_transition(self, pda_example: PDA): - """ Tests the pda transition removal """ + def test_remove_transition(self, pda_example: PDA) -> None: + """Tests the pda transition removal.""" pda = pda_example assert ("q0", "0", "Z0", "q1", ("Z1", "Z0")) in pda pda.remove_transition("q0", "0", "Z0", "q1", ("Z1", "Z0")) @@ -415,8 +456,8 @@ def test_remove_transition(self, pda_example: PDA): pda.remove_transition("a", "b", "c", "d", ["e"]) assert pda.get_number_transitions() == 2 - def test_iteration(self, pda_example: PDA): - """ Tests the iteration of pda transitions """ + def test_iteration(self, pda_example: PDA) -> None: + """Tests the iteration of pda transitions.""" pda = pda_example transitions = list(iter(pda)) assert (("q0", "0", "Z0"), ("q1", ("Z1", "Z0"))) in transitions diff --git a/pyformlang/regular_expression/tests/test_python_regex.py b/pyformlang/regular_expression/tests/test_python_regex.py index c0743c0..55b6a1a 100644 --- a/pyformlang/regular_expression/tests/test_python_regex.py +++ b/pyformlang/regular_expression/tests/test_python_regex.py @@ -1,6 +1,4 @@ -""" -Testing python regex parsing -""" +"""Testing python regex parsing.""" import re @@ -8,24 +6,24 @@ class TestPythonRegex: - """ Tests for python regex """ + """Tests for python regex.""" # pylint: disable=missing-function-docstring, too-many-public-methods - def test_simple(self): + def test_simple(self) -> None: regex = PythonRegex("abc") assert regex.accepts(["a", "b", "c"]) assert not regex.accepts(["a", "b", "b"]) assert not regex.accepts(["a", "b"]) - def test_with_brackets(self): + def test_with_brackets(self) -> None: regex = PythonRegex("a[bc]") assert regex.accepts(["a", "b"]) assert regex.accepts(["a", "c"]) assert not regex.accepts(["a", "b", "c"]) assert not regex.accepts(["a", "a"]) - def test_range_in_brackets(self): + def test_range_in_brackets(self) -> None: regex = PythonRegex("a[a-z]") assert regex.accepts(["a", "a"]) assert regex.accepts(["a", "c"]) @@ -34,7 +32,7 @@ def test_range_in_brackets(self): assert not regex.accepts(["a", "b", "c"]) assert not regex.accepts(["a", "A"]) - def test_range_in_brackets_trap(self): + def test_range_in_brackets_trap(self) -> None: regex = PythonRegex("a[a-e-z]") assert regex.accepts(["a", "a"]) assert regex.accepts(["a", "c"]) @@ -43,25 +41,25 @@ def test_range_in_brackets_trap(self): assert not regex.accepts(["a", "y"]) assert not regex.accepts(["a", "f"]) - def test_range_in_brackets_trap2(self): + def test_range_in_brackets_trap2(self) -> None: regex = PythonRegex("[a-e-g-z]*") assert regex.accepts(["a", "-", "y"]) - def test_range_in_brackets_trap2_bis(self): + def test_range_in_brackets_trap2_bis(self) -> None: regex = PythonRegex(re.compile("[a-e-g-z]*")) assert regex.accepts(["a", "-", "y"]) - def test_parenthesis(self): + def test_parenthesis(self) -> None: regex = PythonRegex("((a)|(b))+") assert regex.accepts(["a", "b"]) - def test_plus(self): + def test_plus(self) -> None: regex = PythonRegex("a+") assert not regex.accepts([]) assert regex.accepts(["a"]) assert regex.accepts(["a", "a"]) - def test_dot(self): + def test_dot(self) -> None: regex = PythonRegex("a.") assert regex.accepts(["a", "b"]) assert regex.accepts(["a", "?"]) @@ -76,153 +74,155 @@ def test_dot(self): assert regex.accepts(["a", "$"]) self._test_compare(".", "\n") - def test_dot_spaces(self): + def test_dot_spaces(self) -> None: regex = PythonRegex("a.") assert regex.accepts(["a", " "]) assert regex.accepts(["a", "\t"]) assert regex.accepts(["a", "\v"]) assert regex.accepts(["a", "\r"]) - def test_simple_optional(self): + def test_simple_optional(self) -> None: regex = PythonRegex("ab?") assert regex.accepts(["a"]) assert regex.accepts(["a", "b"]) assert not regex.accepts(["a", "a"]) - def test_with_parenthesis_optional(self): + def test_with_parenthesis_optional(self) -> None: regex = PythonRegex("a(bb|c)?") assert regex.accepts(["a"]) assert regex.accepts(["a", "b", "b"]) assert regex.accepts(["a", "c"]) assert not regex.accepts(["a", "b"]) - def test_escape_question_mark(self): + def test_escape_question_mark(self) -> None: regex = PythonRegex(r"ab\?") assert regex.accepts(["a", "b", "?"]) - def test_escape_kleene_star(self): + def test_escape_kleene_star(self) -> None: regex = PythonRegex(r"ab\*") assert regex.accepts(["a", "b", "*"]) - def test_escape_plus(self): + def test_escape_plus(self) -> None: regex = PythonRegex(r"ab\+") assert regex.accepts(["a", "b", "+"]) assert not regex.accepts(["a", "b", "\\"]) - def test_escape_opening_bracket(self): + def test_escape_opening_bracket(self) -> None: regex = PythonRegex(r"a\[") assert regex.accepts(["a", "["]) - def test_escape_closing_bracket(self): + def test_escape_closing_bracket(self) -> None: regex = PythonRegex(r"a\]") assert regex.accepts(["a", "]"]) - def test_escape_backslash(self): + def test_escape_backslash(self) -> None: regex = PythonRegex(r"a\\") assert regex.accepts(["a", "\\"]) - def test_escape_backslash_plus(self): + def test_escape_backslash_plus(self) -> None: regex = PythonRegex(r"a\\+") assert regex.accepts(["a", "\\", "\\"]) - def test_escape_backslash_opening_bracket(self): + def test_escape_backslash_opening_bracket(self) -> None: regex = PythonRegex(r"a\\[ab]") assert regex.accepts(["a", "\\", "a"]) assert regex.accepts(["a", "\\", "b"]) self._test_compare(r"a\\[ab]", "a\\a") - def test_escape_backslash_closing_bracket(self): + def test_escape_backslash_closing_bracket(self) -> None: self._test_compare(r"a[ab\\]", "aa") self._test_compare(r"a[ab\\]", "ab") self._test_compare(r"a[ab\\]", "a\\") - def test_escape_backslash_question_mark(self): + def test_escape_backslash_question_mark(self) -> None: regex = PythonRegex(r"a\\?") assert regex.accepts(["a"]) assert regex.accepts(["a", "\\"]) assert not regex.accepts(["a", "\\", "?"]) assert not regex.accepts(["a", "\\?"]) - def test_escape_dash_in_brackets(self): + def test_escape_dash_in_brackets(self) -> None: regex = PythonRegex(r"a[a\-]") assert regex.accepts(["a", "a"]) assert regex.accepts(["a", "-"]) - def test_special_in_brackets_opening_parenthesis(self): + def test_special_in_brackets_opening_parenthesis(self) -> None: regex = PythonRegex(r"a[a(]") assert regex.accepts(["a", "a"]) assert regex.accepts(["a", "("]) - def test_special_in_brackets_closing_parenthesis(self): + def test_special_in_brackets_closing_parenthesis(self) -> None: regex = PythonRegex(r"a[a)]") assert regex.accepts(["a", "a"]) assert regex.accepts(["a", ")"]) - def test_special_in_brackets_kleene_star(self): + def test_special_in_brackets_kleene_star(self) -> None: regex = PythonRegex(r"a[a*]") assert regex.accepts(["a", "a"]) assert regex.accepts(["a", "*"]) assert not regex.accepts(["a", "a", "a"]) - def test_special_in_brackets_positive_closure(self): + def test_special_in_brackets_positive_closure(self) -> None: regex = PythonRegex(r"a[a+]") assert regex.accepts(["a", "a"]) assert regex.accepts(["a", "+"]) assert not regex.accepts(["a", "a", "a"]) - def test_special_in_brackets_optional(self): + def test_special_in_brackets_optional(self) -> None: regex = PythonRegex(r"a[a?]") assert regex.accepts(["a", "a"]) assert regex.accepts(["a", "?"]) assert not regex.accepts(["a"]) - def test_shortcut_digits(self): + def test_shortcut_digits(self) -> None: regex = PythonRegex(r"a\d") assert regex.accepts(["a", "0"]) assert regex.accepts(["a", "1"]) - def test_shortcut_digits_in_brackets(self): + def test_shortcut_digits_in_brackets(self) -> None: regex = PythonRegex(r"a[\da]") assert regex.accepts(["a", "0"]) assert regex.accepts(["a", "1"]) assert regex.accepts(["a", "a"]) - def test_shortcut_spaces(self): + def test_shortcut_spaces(self) -> None: regex = PythonRegex(r"a\s") assert regex.accepts(["a", " "]) assert regex.accepts(["a", "\t"]) - def test_space(self): + def test_space(self) -> None: regex = PythonRegex(" ") assert regex.accepts([" "]) - def test_shortcut_word(self): + def test_shortcut_word(self) -> None: regex = PythonRegex(r"a\w") assert regex.accepts(["a", "0"]) assert regex.accepts(["a", "_"]) assert regex.accepts(["a", "A"]) assert regex.accepts(["a", "f"]) - def _test_compare(self, regex, s_test): + def _test_compare(self, regex: str, s_test: str) -> None: r_pyformlang = PythonRegex(regex) r_python = re.compile(regex) - assert (r_python.fullmatch(s_test) is not None) == r_pyformlang.accepts(s_test) + assert (r_python.fullmatch(s_test) is not None) == r_pyformlang.accepts( + s_test + ) - def test_backslash(self): + def test_backslash(self) -> None: self._test_compare(".*", "\\") self._test_compare(".*", "]") - def test_escape_dot(self): + def test_escape_dot(self) -> None: self._test_compare("\\.", ".") - def test_brackets(self): + def test_brackets(self) -> None: self._test_compare(r"[{-}]", "}") self._test_compare(r"[{}]", "{") self._test_compare(r"[{-}]", "{") self._test_compare(r"[{-}]", "-") self._test_compare(r"[{-}]", "|") - def test_brackets_escape(self): + def test_brackets_escape(self) -> None: self._test_compare(r"[\[]", "[") self._test_compare(r"[Z-\[]", "Z") self._test_compare(r"[Z-\[]", "[") @@ -235,14 +235,14 @@ def test_brackets_escape(self): self._test_compare(r"[\]-a]", "]") self._test_compare(r"[\]-a]", "a") - def test_brackets_end_range_escaped(self): + def test_brackets_end_range_escaped(self) -> None: self._test_compare(r"[{-\}]", "|") self._test_compare(r"[{\}]", "{") self._test_compare(r"[{-\}]", "{") self._test_compare(r"[{-\}]", "-") self._test_compare(r"[{-\}]", "}") - def test_brackets_backslash_middle(self): + def test_brackets_backslash_middle(self) -> None: self._test_compare(r"[a\b]", "b") self._test_compare(r"[a\b]", "\b") self._test_compare(r"[a\\b]", "a") @@ -252,7 +252,7 @@ def test_brackets_backslash_middle(self): self._test_compare(r"[a\b]", "\\b") self._test_compare(r"[a\b]", "\\") - def test_backslash2(self): + def test_backslash2(self) -> None: self._test_compare(r"\t", "t") self._test_compare(r"\t", "\t") self._test_compare(r"\t", "\\t") @@ -260,13 +260,13 @@ def test_backslash2(self): self._test_compare(r"(a | \t)", "\t") self._test_compare(r"(a | \t)", "\\t") - def test_octal(self): + def test_octal(self) -> None: self._test_compare(r"\x10", "\x10") self._test_compare(r"\110", "\110") self._test_compare(r"\\\\x10", "\x10") self._test_compare(r"\\\\x10", "\\x10") - def test_backspace(self): + def test_backspace(self) -> None: self._test_compare(r"a[b\b]", "ab") self._test_compare(r"a[b\b]", "a\b") self._test_compare(r"\ba[b\b]", "ab") @@ -274,16 +274,16 @@ def test_backspace(self): self._test_compare(r"a[b|\b]", "ab") self._test_compare(r"a[b|\b]", "a|") - def test_unicode_name(self): + def test_unicode_name(self) -> None: self._test_compare(r" ", " ") self._test_compare(r"\N{space}", " ") self._test_compare(r"\N{space}", "a") - def test_unicode(self): + def test_unicode(self) -> None: self._test_compare(r"\u1111", "\u1111") self._test_compare(r"\U00001111", "\U00001111") - def test_dot_harder(self): + def test_dot_harder(self) -> None: self._test_compare(r"\\.", "\\a") self._test_compare(r"\\.", "\\.") self._test_compare(r"\.", "a") @@ -291,7 +291,7 @@ def test_dot_harder(self): self._test_compare(r"\\\.", "\\a") self._test_compare(r"\\\.", "\\.") - def test_single_repetition(self): + def test_single_repetition(self) -> None: self._test_compare(r"\d{3}-\d{3}-\d{4}", "012-876-3789") self._test_compare(r"a{5}b", "ab") self._test_compare(r"a{5}b", "aaaaab") @@ -299,7 +299,7 @@ def test_single_repetition(self): self._test_compare(r"a{5b", "a{5b") self._test_compare(r"T{4}P{3}", "TTTTTTPPPPPPPPPPPP") - def test_range_repetition(self): + def test_range_repetition(self) -> None: self._test_compare(r"a{2,5}b", "ab") self._test_compare(r"a{2,5}b", "aab") self._test_compare(r"a{2,5}b", "aaaaab") @@ -316,14 +316,16 @@ def test_range_repetition(self): self._test_compare(r"[a-z]{1,3}", "dpo") self._test_compare(r"[a-z]{1,3}", "dpoz") - def test_error_backslash(self): + def test_error_backslash(self) -> None: self._test_compare(r"[a\\\\\\]]", "\\]") self._test_compare(r"\"([d\"\\\\]|\\\\.)*\"", '"d\\"') self._test_compare(r"[a\\\\]", "a") self._test_compare(r"\"([^\"\\\\]|\\\\.)*\"", '"ddd"') - self._test_compare(r"([a-z_]+:\s([^,\n]+,)*[^,\n]*)", "abho-ja: njzk,szi,szkok") + self._test_compare( + r"([a-z_]+:\s([^,\n]+,)*[^,\n]*)", "abho-ja: njzk,szi,szkok" + ) - def test_negation_brackets(self): + def test_negation_brackets(self) -> None: self._test_compare(r"[^abc]*", "") self._test_compare(r"[^abc]*", "a") self._test_compare(r"[^abc]*", "b") @@ -333,7 +335,7 @@ def test_negation_brackets(self): self._test_compare(r"[^abc]*", "dgh") self._test_compare(r"[^?]*", "dgh") - def test_question_mark(self): + def test_question_mark(self) -> None: self._test_compare(r".", "?") self._test_compare(r"a(a|b)?", "a") self._test_compare(r"a(a|b)\?", "ab?") diff --git a/pyformlang/regular_expression/tests/test_regex.py b/pyformlang/regular_expression/tests/test_regex.py index c875544..750d189 100644 --- a/pyformlang/regular_expression/tests/test_regex.py +++ b/pyformlang/regular_expression/tests/test_regex.py @@ -1,6 +1,4 @@ -""" -Tests for regular expressions -""" +"""Tests for regular expressions.""" import pytest @@ -9,17 +7,21 @@ from pyformlang.finite_automaton import DeterministicFiniteAutomaton from pyformlang.finite_automaton import State, Symbol, Epsilon from pyformlang.finite_automaton.tests.test_deterministic_finite_automaton \ - import get_example0, get_dfa_example, perform_tests_example0 + import ( + get_example0, + get_dfa_example, + perform_tests_example0, +) class TestRegex: - """ Tests for regex """ + """Tests for regex.""" # pylint: disable=missing-function-docstring,too-many-public-methods # pylint: disable=protected-access - def test_creation(self): - """ Try to create regex """ + def test_creation(self) -> None: + """Try to create regex.""" regex = Regex("a|b") assert regex.get_number_symbols() == 2 assert regex.get_number_operators() == 1 @@ -70,8 +72,8 @@ def test_creation(self): assert regex.get_number_symbols() == 4 assert regex.get_number_operators() == 3 - def test_to_enfa0(self): - """ Tests the transformation to a regex """ + def test_to_enfa0(self) -> None: + """Tests the transformation to a regex.""" symb_a = Symbol("a") symb_b = Symbol("b") symb_c = Symbol("c") @@ -112,8 +114,8 @@ def test_to_enfa0(self): assert enfa.accepts([symb_a, symb_a]) assert enfa.accepts([symb_a, symb_a, symb_a]) - def test_to_enfa1(self): - """ Tests the transformation to a regex """ + def test_to_enfa1(self) -> None: + """Tests the transformation to a regex.""" symb_a = Symbol("a") symb_b = Symbol("b") symb_c = Symbol("c") @@ -154,8 +156,8 @@ def test_to_enfa1(self): assert not enfa.accepts([symb_c]) assert enfa.accepts([]) - def test_print(self): - """ Test printing functions """ + def test_print(self) -> None: + """Test printing functions.""" regex = Regex("a*.(b|c)epsilon") tree_str = regex.get_tree_str() assert "Concatenation" in tree_str @@ -166,7 +168,7 @@ def test_print(self): tree_str = regex.get_tree_str() assert "Empty" in tree_str - def test_get_repr(self): + def test_get_repr(self) -> None: regex0 = Regex("a*.(b|c)epsilon") regex_str = str(regex0) regex1 = Regex(regex_str) @@ -174,79 +176,81 @@ def test_get_repr(self): dfa1 = regex1.to_minimal_dfa() assert dfa0 == dfa1 - def test_accepts(self): + def test_accepts(self) -> None: regex = Regex("a|b|c") assert regex.accepts(["a"]) assert not regex.accepts(["a", "b"]) - def test_space(self): + def test_space(self) -> None: regex = Regex("\\ ") assert regex.accepts([" "]) - def test_parenthesis_gorilla(self): + def test_parenthesis_gorilla(self) -> None: regex = Regex("george touches (a|an) (sky|gorilla) !") assert regex.accepts(["george", "touches", "a", "sky", "!"]) - def test_regex_or(self): + def test_regex_or(self) -> None: regex = Regex("a|b") assert regex.accepts(["a"]) - def test_regex_or_concat(self): + def test_regex_or_concat(self) -> None: regex = Regex("c (a|b)") assert regex.accepts(["c", "b"]) - def test_regex_two_or_concat(self): + def test_regex_two_or_concat(self) -> None: regex = Regex("c (a|b) (d|e)") assert regex.accepts(["c", "b", "e"]) - def test_regex_two_or_concat_parenthesis(self): + def test_regex_two_or_concat_parenthesis(self) -> None: regex = Regex("c.(a|b)(d|e)") assert regex.accepts(["c", "b", "e"]) - def test_regex_two_or_concat_parenthesis2(self): + def test_regex_two_or_concat_parenthesis2(self) -> None: regex = Regex("c (a|(b d)|e)") assert regex.accepts(["c", "a"]) assert regex.accepts(["c", "b", "d"]) assert regex.accepts(["c", "e"]) - def test_regex_two_or_concat_parenthesis2_concat(self): + def test_regex_two_or_concat_parenthesis2_concat(self) -> None: regex = Regex("c (a|(b d)|e) !") assert regex.accepts(["c", "a", "!"]) assert regex.accepts(["c", "b", "d", "!"]) assert regex.accepts(["c", "e", "!"]) - def test_regex_or_two_concat(self): + def test_regex_or_two_concat(self) -> None: regex = Regex("c d (a|b)") assert regex.accepts(["c", "d", "b"]) - def test_after_union(self): + def test_after_union(self) -> None: regex = Regex("(a|b) !") assert regex.accepts(["a", "!"]) - def test_star_union(self): + def test_star_union(self) -> None: regex = Regex("a*(b|c)") assert regex.accepts(["a", "a", "c"]) - def test_misformed(self): + def test_misformed(self) -> None: with pytest.raises(MisformedRegexError): Regex(")") - def test_misformed2(self): + def test_misformed2(self) -> None: with pytest.raises(MisformedRegexError): Regex("(") - def test_escaped_parenthesis(self): + def test_escaped_parenthesis(self) -> None: regex = Regex("\\(") assert regex.accepts(["("]) - def test_escaped_mid_bar(self): - regex = Regex('a(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q' - '|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|' - 'S|T|U|V|W|X|Y|Z|!|"|#|\\$|%|&|\'|\\(|\\)|\\*|\\+|,|-|' - '\\.|/|:|;|<|=|>|?|@|[|\\|]|^|_|`|{|\\||}|~|\\ | |)') + def test_escaped_mid_bar(self) -> None: + regex = Regex( + "a(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q" + "|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|" + "S|T|U|V|W|X|Y|Z|!|\"|#|\\$|%|&|'|\\(|\\)|\\*|\\+|,|-|" + "\\.|/|:|;|<|=|>|?|@|[|\\|]|^|_|`|{|\\||}|~|\\ | |)" + ) assert regex.accepts(["a", "|"]) - def test_to_cfg(self): + def test_to_cfg(self) -> None: regex = Regex("a") cfg = regex.to_cfg() assert cfg.contains(["a"]) @@ -273,22 +277,22 @@ def test_to_cfg(self): assert cfg.contains(["a", "c"]) assert cfg.contains(["a", "b", "c"]) - def test_priority(self): - assert Regex('b a* | a').accepts('a') - assert Regex('b a* | a').accepts('b') - assert Regex('(b a*) | a').accepts('a') + def test_priority(self) -> None: + assert Regex("b a* | a").accepts("a") + assert Regex("b a* | a").accepts("b") + assert Regex("(b a*) | a").accepts("a") - def test_backslash_b(self): + def test_backslash_b(self) -> None: assert Regex("( a | \b )").accepts("\b") assert Regex("( a | \b )").accepts("a") assert not Regex("( a | \b )").accepts("b") - def test_backslash(self): + def test_backslash(self) -> None: assert Regex("(\\\\|])").accepts("\\") assert Regex("(\\\\|])").accepts("]") - def test_remove_state(self): - " Tests the remove of state """ + def test_remove_state(self) -> None: + " Tests the remove of state " "" enfa = EpsilonNFA() state0 = State(0) state1 = State(1) @@ -307,8 +311,8 @@ def test_remove_state(self): assert enfa.get_number_transitions() == 1 assert len(enfa.states) == 2 - def test_from_enfa1(self): - """ Tests the transformation to regex """ + def test_from_enfa1(self) -> None: + """Tests the transformation to regex.""" enfa = EpsilonNFA() state0 = State(0) state1 = State(1) @@ -358,8 +362,8 @@ def test_from_enfa1(self): assert not enfa3.accepts([symb_e]) assert enfa3.accepts([symb_f]) - def test_from_enfa2(self): - """ Tests the transformation to regex """ + def test_from_enfa2(self) -> None: + """Tests the transformation to regex.""" enfa = EpsilonNFA() state0 = State(0) state1 = State(1) @@ -377,14 +381,12 @@ def test_from_enfa2(self): assert enfa2.accepts([symb_a, symb_a]) assert enfa2.accepts([symb_a, symb_a, symb_b]) assert enfa2.accepts([symb_a, symb_a, symb_b, symb_b]) - assert enfa2.accepts([symb_a, symb_a, - symb_b, symb_b, symb_a]) - assert enfa2.accepts([symb_a, symb_a, symb_b, - symb_b, symb_a, symb_b]) + assert enfa2.accepts([symb_a, symb_a, symb_b, symb_b, symb_a]) + assert enfa2.accepts([symb_a, symb_a, symb_b, symb_b, symb_a, symb_b]) assert not enfa2.accepts([symb_b]) - def test_from_enfa3(self): - """ Tests the transformation to regex """ + def test_from_enfa3(self) -> None: + """Tests the transformation to regex.""" enfa = EpsilonNFA() state0 = State(0) state1 = State(1) @@ -400,10 +402,10 @@ def test_from_enfa3(self): assert not enfa2.accepts([symb_a]) assert not enfa2.accepts([symb_a, symb_a]) assert not enfa2.accepts([symb_a, symb_a, symb_b]) - assert not enfa2.accepts([symb_a, symb_a, - symb_b, symb_b, symb_a]) - assert not enfa2.accepts([symb_a, symb_a, symb_b, - symb_b, symb_a, symb_b]) + assert not enfa2.accepts([symb_a, symb_a, symb_b, symb_b, symb_a]) + assert not enfa2.accepts( + [symb_a, symb_a, symb_b, symb_b, symb_a, symb_b] + ) assert not enfa2.accepts([symb_b]) epsilon = Epsilon() enfa.add_transition(state0, epsilon, state1) @@ -414,8 +416,7 @@ def test_from_enfa3(self): assert enfa2.accepts([symb_a]) assert enfa2.accepts([symb_a, symb_a]) assert enfa2.accepts([symb_a, symb_a, symb_b, symb_b]) - assert enfa2.accepts([symb_a, symb_a, symb_b, symb_b, - symb_a, symb_b]) + assert enfa2.accepts([symb_a, symb_a, symb_b, symb_b, symb_a, symb_b]) assert enfa2.accepts([symb_b]) assert enfa2.accepts([]) enfa.remove_transition(state0, symb_a, state0) @@ -424,10 +425,10 @@ def test_from_enfa3(self): assert not enfa2.accepts([symb_a]) assert not enfa2.accepts([symb_a, symb_a]) assert not enfa2.accepts([symb_a, symb_a, symb_b]) - assert not enfa2.accepts([symb_a, symb_a, symb_b, - symb_b, symb_a]) - assert not enfa2.accepts([symb_a, symb_a, symb_b, symb_b, - symb_a, symb_b]) + assert not enfa2.accepts([symb_a, symb_a, symb_b, symb_b, symb_a]) + assert not enfa2.accepts( + [symb_a, symb_a, symb_b, symb_b, symb_a, symb_b] + ) assert enfa2.accepts([symb_b]) assert enfa2.accepts([]) enfa.remove_transition(state1, symb_b, state1) @@ -439,7 +440,7 @@ def test_from_enfa3(self): enfa2 = regex.to_epsilon_nfa() assert enfa2.accepts([symb_a, symb_b]) - def test_example_doc(self): + def test_example_doc(self) -> None: enfa0 = EpsilonNFA() state0 = State(0) state1 = State(1) @@ -459,19 +460,19 @@ def test_example_doc(self): dfa1 = DeterministicFiniteAutomaton.from_epsilon_nfa(enfa1) assert dfa0.is_equivalent_to(dfa1) - def test_from_dfa0(self): - """ Tests the regex transformation """ + def test_from_dfa0(self) -> None: + """Tests the regex transformation.""" dfa0 = get_example0() enfa = Regex.from_finite_automaton(dfa0).to_epsilon_nfa() perform_tests_example0(enfa) - def test_from_dfa1(self): + def test_from_dfa1(self) -> None: dfa1 = get_dfa_example() enfa = Regex.from_finite_automaton(dfa1).to_epsilon_nfa() dfa2 = DeterministicFiniteAutomaton.from_epsilon_nfa(enfa) assert dfa1.is_equivalent_to(dfa2) - def test_to_minimal_dfa(self): + def test_to_minimal_dfa(self) -> None: dfa0 = get_example0() dfa_regex = Regex.from_finite_automaton(dfa0) dfa1 = dfa_regex.to_minimal_dfa() diff --git a/pyformlang/rsa/tests/test_rsa.py b/pyformlang/rsa/tests/test_rsa.py index bba62d2..5679fb4 100644 --- a/pyformlang/rsa/tests/test_rsa.py +++ b/pyformlang/rsa/tests/test_rsa.py @@ -1,4 +1,5 @@ -""" Tests for RSA """ +"""Tests for RSA.""" + from pyformlang.finite_automaton import Symbol from pyformlang.regular_expression import Regex @@ -7,9 +8,10 @@ class TestRSA: - """ Test class for RSA """ - def test_creation(self): - """ Test the creation of an RSA """ + """Test class for RSA.""" + + def test_creation(self) -> None: + """Test the creation of an RSA.""" # S -> a S b | a b regex = Regex("a S b | a b") dfa = regex.to_minimal_dfa() @@ -25,8 +27,8 @@ def test_creation(self): assert rsa_2 == rsa_1 - def test_from_regex(self): - """ Test creation of an RSA from a regex""" + def test_from_regex(self) -> None: + """Test creation of an RSA from a regex.""" # S -> a* rsa_2 = RecursiveAutomaton.from_regex(Regex("a*"), "S") @@ -36,8 +38,8 @@ def test_from_regex(self): assert rsa_2 == rsa_1 - def test_is_equals_to(self): - """ Test the equals of two RSAs""" + def test_is_equals_to(self) -> None: + """Test the equals of two RSAs.""" # S -> a* b* rsa_1 = RecursiveAutomaton.from_regex(Regex("a* b*"), "S") @@ -46,12 +48,11 @@ def test_is_equals_to(self): assert rsa_1 != rsa_2 - def test_from_ebnf(self): - """ Test reading RSA from ebnf""" + def test_from_ebnf(self) -> None: + """Test reading RSA from ebnf.""" # g1: S -> a S b | a b rsa1_g1 = RecursiveAutomaton.from_ebnf("S -> a S b | a b") - rsa2_g1 = RecursiveAutomaton.from_regex( - Regex("a S b | a b"), "S") + rsa2_g1 = RecursiveAutomaton.from_regex(Regex("a S b | a b"), "S") assert rsa1_g1 == rsa2_g1 diff --git a/ruff.toml b/ruff.toml index 2080912..383dc67 100644 --- a/ruff.toml +++ b/ruff.toml @@ -56,3 +56,4 @@ indent-style = "space" line-ending = "auto" docstring-code-format = false docstring-code-line-length = "dynamic" +skip-magic-trailing-comma = true