Exemple #1
0
def test_recommend_simple_programs_3(expected_programs, commands):
    rec = Recommendations(db)
    rec.run_pipeline(
        [{"operation": operation, "data": data} for (operation, data) in commands]
        + [{"operation": "include", "data": base_3}]
    )
    print(rec.selected_programs)
    assert rec.selected_programs == expected_programs
Exemple #2
0
def test_recommend_programming_idioms(capsys):
    path = Path("examples/idioms/programs_db.json")
    rec = Recommendations(db=json.loads(path.read_text()))
    rec.run_pipeline()
    output_path = path.parent / "programs_recommendations.md"
    rec.get_markdown()  # for coverage
    make_snapshot(
        output_path,
        rec.get_markdown(sorting_strategy="lexicographic", grouping_strategy="no_group"),
        capsys,
    )
def test_recommend_mini_programs():
    db = json.loads(Path("examples/mini/programs_db.json").read_text())
    proper_taxa = {}
    for program in [
            "assignment.py", "collatz.py", "fizzbuzz.py", "is_even.py"
    ]:
        proper_taxa[program] = set(db["programs"][program]["taxa"])

    rec = Recommendations(db)
    original = proper_taxa["fizzbuzz.py"] | proper_taxa["collatz.py"]
    assert all(
        taxon.startswith("meta") for taxon in original.difference(
            db["programs"]["fizzbuzz.py"]["taxa"]))

    commands = [{
        "operation":
        "exclude",
        "data": [
            "assignment.py",
            "fizzbuzz.py",  # imported by is_even.py, consequently excluded
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"collatz.py"}
    assert not rec.imparted_knowledge

    # A command excluding a sequence is equivalent to a sequence of excluding commands
    commands = [
        {
            "operation": "exclude",
            "data": ["assignment.py"]
        },
        {
            "operation": "exclude",
            "data": ["fizzbuzz.py"]
        },
    ]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"collatz.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation": "include",
        "data": ["this_program_does_not_exist.py"]
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert not rec.selected_programs
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "include",
        "data": [
            "assignment.py",
            "fizzbuzz.py",  # imported by is_even.py, which nevertheless will not be included
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"assignment.py", "fizzbuzz.py"}
    assert not rec.imparted_knowledge

    # A command including a sequence is not equivalent to a sequence of including commands
    commands = [
        {
            "operation": "include",
            "data": ["assignment.py"]
        },
        {
            "operation": "include",
            "data": ["fizzbuzz.py"]
        },
    ]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert not rec.selected_programs
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "impart",
        "data": [
            "assignment.py",  # exclude it, and impart its taxa
            "fizzbuzz.py",  # idem, but ignore its imports or exports
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"collatz.py", "is_even.py"}
    assert proper_taxa["assignment.py"].issubset(rec.imparted_knowledge)
    assert proper_taxa["fizzbuzz.py"].issubset(rec.imparted_knowledge)
    assert not proper_taxa["is_even.py"].issubset(rec.imparted_knowledge)
    assert not proper_taxa["collatz.py"].issubset(rec.imparted_knowledge)

    commands = [{"operation": "impart", "data": ["operator/arithmetic"]}]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {
        "assignment.py", "collatz.py", "fizzbuzz.py", "is_even.py"
    }
    print(rec.imparted_knowledge)
    assert rec.imparted_knowledge == {
        "operator/arithmetic/multiplication",
        "operator/arithmetic/modulo",
        "operator",
        "operator/arithmetic",
        "operator/arithmetic/addition",
    }

    commands = [{
        "operation":
        "exclude",
        "data": [
            "var/assignment/explicit/single",  # featured directly by assignment.py
            # and collatz.py, which is imported by fizzbuzz.py and is_even.py
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert not rec.selected_programs
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "exclude",
        "data": [
            "flow/conditional/else/if",  # featured directly by fizzbuzz.py,
            # which is imported by is_even.py
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"assignment.py", "collatz.py"}

    commands = [{
        "operation":
        "include",
        "data": [
            ("meta/program", "not contains", "flow/conditional/else/if"),
            # There is a subtle difference with the previous one, since "exclude" follows the
            # importations, while "include" does not.
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {
        "assignment.py", "collatz.py", "is_even.py"
    }

    commands = [{
        "operation": "include",
        "data": [
            "flow/conditional/else/if",
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"fizzbuzz.py"}

    commands = [{
        "operation":
        "exclude",
        "data": [
            ("meta/program", "not contains", "flow/conditional/else/if"),
            # "assignment.py", "is_even.py", "collatz.py" are excluded since they don't feature
            # an `elif`. "fizzbuzz.py" features an `elif`, but is excluded since it imports an
            # excluded program ("collatz.py").
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert not rec.selected_programs

    commands = [{
        "operation":
        "exclude",
        "data": [
            "flow/conditional/else/if",  # Although not recommended, it is possible to mix
            "assignment.py"  # taxa and programs (ending with ".py") in a same command.
            # Crucially, this avoids to specify whether the command should be applied on
            # taxa or programs.
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"collatz.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "include",
        "data": [
            "var/assignment/explicit/single",  # featured by assignment.py and collatz.py
            # Although the latter is imported by both fizzbuzz.py and is_even.py, they are
            # not included in the result
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"assignment.py", "collatz.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation": "include",
        "data": ["this_taxon_does_not_exist"]
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert not rec.selected_programs
    assert not rec.imparted_knowledge

    commands = [{
        "operation": "include",
        "data": [
            ("var/assignment/explicit", "inside", "flow/loop"),
        ],  # featured by collatz.py only
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"collatz.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "exclude",
        "data": [
            ("var/assignment/explicit", "inside",
             "flow/loop"),  # featured by collatz.py,
            # and indirectly by fizzbuzz.py and is_even.py
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"assignment.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "include",
        "data": [
            ("var/assignment/explicit", "not inside",
             "flow/loop"),  # Must read as:
            # Include all programs featuring an assignment, except those where this assignment
            # is inside a loop. Hence, this includes assignment.py, even if it does not feature
            # a loop.
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"assignment.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "include",
        "data": [
            ("var/assignment/explicit", "inside",
             "meta/program"),  # This comes down to
            # including all programs featuring an assignment.
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    print(rec.selected_programs)
    assert rec.selected_programs == {"assignment.py", "collatz.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "include",
        "data": [
            ("var/assignment/explicit", "not inside",
             "meta/program"),  # This comes down to
            # exclude all programs either featuring or not featuring an assignment!
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    print(rec.selected_programs)
    assert not rec.selected_programs
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "impart",  # Imparting triples is currently not supported (ignored).
        "data": [("var/assignment/explicit", "inside", "flow/loop")],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {
        "assignment.py",
        "collatz.py",
        "fizzbuzz.py",
        "is_even.py",
    }
    assert not rec.imparted_knowledge

    commands = [{
        "operation": "include",
        "data": 42
    }]  # malformed source => ignored command
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {
        "assignment.py",
        "collatz.py",
        "fizzbuzz.py",
        "is_even.py",
    }
    assert not rec.imparted_knowledge

    commands = [{
        "operation": "include",
        "data": [42]
    }]  # malformed pattern => ignored pattern
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == set()
    assert not rec.imparted_knowledge

    commands = [{"data": []}]  # a command without operation is ignored
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {
        "assignment.py",
        "collatz.py",
        "fizzbuzz.py",
        "is_even.py",
    }
    assert not rec.imparted_knowledge

    commands = [{
        "operation": "undefined_command",  # an undefined command is ignored
        "data": "assignment.py",
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {
        "assignment.py",
        "collatz.py",
        "fizzbuzz.py",
        "is_even.py",
    }
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "exclude",
        "data": [
            ("var/assignment/explicit/single", "after",
             "call/function/builtin/print"),
            # collatz.py and fizzbuzz.py have an assignment after a print.
            # is_even.py imports fizzbuzz.py.
            # Consequently, these three programs are excluded.
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"assignment.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "exclude",
        "data": [
            ("operator/arithmetic/addition", "equals",
             "operator/arithmetic/multiplication"),
            # "operator/arithmetic/addition" and "operator/arithmetic/multiplication" are both
            # featured on the same line of collatz.py, and indirectly by fizzbuzz.py and
            # is_even.py. Therefore, excluding this taxon keeps only assignment.py.
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"assignment.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "exclude",
        "data": [
            ("condition/equality", "inside", "def/function"),
            # "condition/equality" is inside "def/function" in is_even.py, which is not
            # imported anywhere.
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {
        "collatz.py", "assignment.py", "fizzbuzz.py"
    }
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "exclude",
        "data": [
            ("call/function/builtin/range", "inside", "flow/conditional"),
            # "call/function/builtin/range" is not inside "flow/conditional" anywhere.
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {
        "is_even.py",
        "fizzbuzz.py",
        "assignment.py",
        "collatz.py",
    }
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "include",
        "data": [
            ("var/assignment/explicit/single", "after",
             "call/function/builtin/print"),
            # The taxon "var/assignment/explicit/single" is featured by assignment.py and
            # collatz.py. In collatz.py, it appears after a taxon "call/function/builtin/print".
            # Consequently, it should be included in the results, but not the programs which
            # import it: fizzbuzz.py and is_even.py.
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"collatz.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "include",
        "data": [
            ("operator/arithmetic/modulo", "equals",
             "type/number/integer/literal"),
            # "operator/arithmetic/modulo" and "type/number/integer/literal" are both featured
            # on the same line in all programs except assignment.py
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"collatz.py", "is_even.py", "fizzbuzz.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "include",
        "data": [
            ("operator/arithmetic/modulo", "x == y",
             "type/number/integer/literal"),
            # The same with "x == y" instead of "equals"
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"collatz.py", "is_even.py", "fizzbuzz.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "include",
        "data": [
            ("condition/equality", "inside", "def/function"),
            # "condition/equality" is inside "def/function" in is_even.py, which is not
            # imported anywhere.
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"is_even.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "include",
        "data": [
            ("condition/equality$", "inside", "def"),
            # "condition/equality" (strictly, note the dollar sign) is inside "def/function"
            # in is_even.py and inside "def/procedure" in collatz.py. Both will be
            # included.
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"collatz.py", "is_even.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "include",
        "data": [
            ("call/function/builtin/range", "inside", "flow/conditional"),
            # "call/function/builtin/range" is not inside "flow/conditional" anywhere.
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert not rec.selected_programs
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "include",
        "data": [
            ("call/function/builtin/print", "is",
             "call/function/builtin/print"),
            # "call/function/builtin/print" may appear several times in the same program, but
            # never on the same line.
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert not rec.selected_programs
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "include",
        "data": [
            ("type/number/integer/literal$", "is",
             "type/number/integer/literal$"),
            # "type/number/integer/literal" appears twice on the same line in fizzbuzz.py and
            # collatz.py
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"fizzbuzz.py", "collatz.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "include",
        "data": [
            ("type/number/integer/literal$", "is",
             "type/number/integer/literal$"),
            # "type/number/integer/literal" appears twice on the same line in fizzbuzz.py and
            # collatz.py
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"fizzbuzz.py", "collatz.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "include",
        "data": [
            ("call/function/builtin/print", "not inside",
             "flow/loop/exit/late"),
            # A print statement is featured inside a loop by both collatz.py and fizzbuzz.py.
            # However, in collatz.py, there exists a print statement which is not inside the
            # loop. This makes it satisfy the predicate. Note that assignment.py and is_even.py
            # are not included in the result, since they don't feature (at least directly)
            # "call/function/builtin/print".
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    assert rec.selected_programs == {"collatz.py"}
    assert not rec.imparted_knowledge

    commands = [{
        "operation":
        "exclude",
        "data": [
            ("call/function/builtin/print", "not inside", "flow/loop"),
            # Exclude the programs which feature a print statement outside a loop. This does
            # not exclude assignment.py, which does not feature a print statement. This
            # excludes collatz, which features a print statement outside a loop, even if it
            # also features a print statement inside a loop. fizzbuzz.py and is_even.py are
            # excluded too, since they import collatz.py
        ],
    }]
    rec = Recommendations(db)
    rec.run_pipeline(commands)
    print(rec.selected_programs)
    assert rec.selected_programs == {"assignment.py"}
    assert not rec.imparted_knowledge
def test_recommend_program(capsys):
    rec = Recommendations(
        db=json.loads(Path("examples/dummy/programs_db.json").read_text()),
        base_path=Path("examples/dummy/"),
    )
    rec.run_pipeline(literal_eval(Path("examples/dummy/pipe.py").read_text()))
    print(rec.selected_programs)
    assert rec.selected_programs == {
        "prg2.py",
        # "O/N/P",
        # "Y/T/Q",
        # "Y",
        # "X/S/M/L/R/D",
        # "O",
        # "O/C/H/B",
        # "X/S/M",
        # "X/S/M/L/R",
        # "Y/T",
        # "O/C",
        # "X/G",
        # "X/S/M/L/V",
        # "O/C/H/B/I",
        "prg3.py",
        # "O/N/P",
        # "X/K",
        # "Y/T",
        # "X/S/M/L/V",
        # "O/C/H/B",
        # "X/S/M/L/R",
        # "O/J",
        # "X/S/M",
        # "O/C/F/U",
        # "O/C/H",
        # "X/S",
        # "Y",
        # "O",
        # "X/S/M/L",
        # "Y/E",
    }
    print(rec.result)
    assert rec.result == [
        (5, "impart", ["prg8.py"]),
        (6, "exclude", ["prg7.py", "prg9.py"]),
        (7, "exclude", ["prg4.py", "prg5.py", "prg6.py"]),
        (8, "include", ["prg1.py"]),
        (9, "hide", []),
    ]
    costs = {
        taxon: rec.assess.taxon_cost(taxon)
        for taxon in rec.db_programs["prg2.py"]["taxa"]
    }
    print(costs)
    assert costs == {
        "O/N/P": 0,
        "Y/T/Q": 0.375,
        "Y": 0,
        "X/S/M/L/R/D": 0,
        "O": 0,
        "O/C/H/B": 0,
        "X/S/M": 0,
        "X/S/M/L/R": 0,
        "Y/T": 0.25,
        "O/C": 0,
        "X/G": 0.25,
        "X/S/M/L/V": 0,
        "O/C/H/B/I": 0.03125,
    }
    text = rec.get_markdown(span_column_width=10)
    make_snapshot(Path("examples/dummy/programs_recommendations.md"), text,
                  capsys)
Exemple #5
0
def test_recommend_program(capsys):
    rec = Recommendations(
        commands=literal_eval(Path("tests/data/dummy/pipe.py").read_text()),
        db=json.loads(Path("tests/data/dummy/db.json").read_text()),
        base_path=Path("tests/data/dummy/"),
    )
    rec.run_pipeline()
    print(rec.selected_programs)
    assert rec.selected_programs == {
        "prg2.py": [
            "O/N/P",
            "Y/T/Q",
            "Y",
            "X/S/M/L/R/D",
            "O",
            "O/C/H/B",
            "X/S/M",
            "X/S/M/L/R",
            "Y/T",
            "O/C",
            "X/G",
            "X/S/M/L/V",
            "O/C/H/B/I",
        ],
        "prg3.py": [
            "O/N/P",
            "X/K",
            "Y/T",
            "X/S/M/L/V",
            "O/C/H/B",
            "X/S/M/L/R",
            "O/J",
            "X/S/M",
            "O/C/F/U",
            "O/C/H",
            "X/S",
            "Y",
            "O",
            "X/S/M/L",
            "Y/E",
        ],
    }
    assert [p["filtered_out"] for p in rec.commands] == [
        ["prg8.py"],
        ["prg7.py", "prg9.py"],
        ["prg4.py", "prg5.py", "prg6.py"],
        ["prg1.py"],
    ]
    costs = {
        taxon: rec.taxon_cost(taxon)
        for taxon in rec.selected_programs["prg2.py"]
    }
    print(costs)
    assert costs == {
        "O/N/P": 0,
        "Y/T/Q": 0.375,
        "Y": 0,
        "X/S/M/L/R/D": 0,
        "O": 0,
        "O/C/H/B": 0,
        "X/S/M": 0,
        "X/S/M/L/R": 0,
        "Y/T": 0.25,
        "O/C": 0,
        "X/G": 0.25,
        "X/S/M/L/V": 0,
        "O/C/H/B/I": 0.03125,
    }
    text = rec.get_markdown(span_column_width=10)
    make_snapshot(Path("tests/data/dummy/recommendations.md"), text, capsys)