Esempio n. 1
0
def test_get_cache_file_loc_invariant(s):
    """Property:
        1. Calling cache-file with an empty string raises a value-error.
        2. Returned cache files include __pycache__ as the terminal directory.
        3. Splitting the returned cache-file stem on the system tag yeids the original file stem.
    """
    if len(s) == 0:
        with pytest.raises(ValueError):
            _ = get_cache_file_loc(s)

    else:
        result = get_cache_file_loc(s)
        tag = sys.implementation.cache_tag

        assert result.parent.parts[-1] == "__pycache__"
        assert result.stem.split(tag)[0] == s
Esempio n. 2
0
def test_get_cache_file_loc():
    """Expectation for the pycache results based on system tag."""
    test_file = "first.py"
    tag = sys.implementation.cache_tag
    expected = Path("__pycache__") / ".".join([Path(test_file).stem, tag, "pyc"])
    result = get_cache_file_loc(test_file)

    assert result == expected
Esempio n. 3
0
def test_get_cache_file_loc_link_exception(monkeypatch):
    """Symlink existing cache files raise FileExistsError."""
    def mock_islink(x):
        return True

    monkeypatch.setattr(os.path, "islink", mock_islink)

    with pytest.raises(FileExistsError):
        _ = get_cache_file_loc("symlink.py")
Esempio n. 4
0
def test_get_cache_file_loc_not_file(monkeypatch):
    """Irregular existing cache files will raise FileExistsError"""
    def mock_exists(x):
        return True

    def mock_isfile(x):
        return False

    monkeypatch.setattr(os.path, "exists", mock_exists)
    monkeypatch.setattr(os.path, "isfile", mock_isfile)

    with pytest.raises(FileExistsError):
        _ = get_cache_file_loc("nonregularfile.py")
Esempio n. 5
0
def create_mutant(tree: ast.Module, src_file: str, target_idx: LocIndex,
                  mutation_op: Any) -> Mutant:
    """Create a mutatest in the AST of src_file at sample_idx and update the cache.

    Args:
        tree: AST for the source file
        src_file: source file location on disk
        target_idx: the location to make the mutatest
        mutation_op: the mutatest to apply

    Returns:
        The mutant, and creates the cache file of the mutatest
    """

    # mutate ast and create code binary
    mutant_ast = MutateAST(target_idx=target_idx,
                           mutation=mutation_op,
                           src_file=src_file,
                           readonly=False).visit(tree)

    mutant_code = compile(mutant_ast, str(src_file), "exec")

    # get cache file locations and create directory if needed
    cfile = get_cache_file_loc(src_file)

    # generate cache file pyc machinery for writing the cache file
    loader = importlib.machinery.SourceFileLoader("<py_compile>",
                                                  src_file)  # type: ignore
    source_stats = loader.path_stats(src_file)
    mode = importlib._bootstrap_external._calc_mode(src_file)  # type: ignore

    # create the cache files with the mutatest
    mutant = Mutant(
        mutant_code=mutant_code,
        src_file=Path(src_file),
        cfile=Path(cfile),
        loader=loader,
        source_stats=source_stats,
        mode=mode,
        src_idx=target_idx,
        mutation=mutation_op,
    )

    return mutant
Esempio n. 6
0
def test_get_cache_file_loc_invalid():
    """Empty string will raise a ValueError."""
    with pytest.raises(ValueError):
        _ = get_cache_file_loc(src_file="")
Esempio n. 7
0
    def mutate(self,
               target_idx: LocIndex,
               mutation_op: Any,
               write_cache: bool = False) -> Mutant:
        """Create a mutant from a single LocIndex that is in the Genome.

        Mutation_op must be a valid mutation for the target_idx operation code type.
        Optionally, use write_cache to write the mutant to ``__pycache__`` based on the detected
        location at the time of creation. The Genome AST is unmodified by mutate.

        Args:
            target_idx: the target location index (member of .targets)
            mutation_op: the mutation operation to use
            write_cache: optional flag to write to ``__pycache__``

        Returns:
            The mutant definition

        Raises:
            MutationException: if ``mutation_op`` is not a valid mutation for the location index.
            TypeError: if the source_file property is not set on the Genome.
            ValueError: if the target_idx is not a member of Genome targets.
        """
        op_code = CATEGORIES[target_idx.ast_class]
        valid_mutations = CategoryCodeFilter(codes=(op_code, )).valid_mutations

        if mutation_op not in valid_mutations:
            raise MutationException(
                f"{mutation_op} is not a member of mutation category {op_code}.\n"
                f"Valid mutations for {op_code}: {valid_mutations}.")

        if not self.source_file:
            raise TypeError("Source_file is set to NoneType")

        if target_idx not in self.targets:
            raise ValueError(f"{target_idx} is not in the Genome targets.")

        mutant_ast = MutateAST(
            target_idx=target_idx,
            mutation=mutation_op,
            src_file=self.source_file,
            readonly=False).visit(
                deepcopy(
                    self.ast)  # deepcopy to avoid in-place modification of AST
            )

        # generate cache file pyc machinery for writing the __pycache__ file
        loader = importlib.machinery.SourceFileLoader(  # type: ignore
            "<py_compile>", self.source_file)

        # create the cache files with the mutated AST
        mutant = Mutant(
            mutant_code=compile(mutant_ast, str(self.source_file), "exec"),
            src_file=Path(self.source_file),
            cfile=Path(cache.get_cache_file_loc(self.source_file)),
            loader=loader,
            source_stats=loader.path_stats(self.source_file),
            mode=importlib._bootstrap_external._calc_mode(
                self.source_file),  # type: ignore
            src_idx=target_idx,
            mutation=mutation_op,
        )

        if write_cache:
            mutant.write_cache()

        return mutant