<commit_before>"""Rewrite assertion AST to produce nice error messages"""
import ast
import errno
import importlib.machinery
import importlib.util
import itertools
import marshal
import os
import struct
import sys
import types

import atomicwrites

from _pytest._io.saferepr import saferepr
from _pytest._version import version
from _pytest.assertion import util
from _pytest.assertion.util import (  # noqa: F401
    format_explanation as _format_explanation,
)
from _pytest.pathlib import fnmatch_ex
from _pytest.pathlib import PurePath

# pytest caches rewritten pycs in __pycache__.
PYTEST_TAG = "{}-pytest-{}".format(sys.implementation.cache_tag, version)
PYC_EXT = ".py" + (__debug__ and "c" or "o")
PYC_TAIL = "." + PYTEST_TAG + PYC_EXT


class AssertionRewritingHook:
    """PEP302/PEP451 import hook which rewrites asserts."""

    def __init__(self, config):
        self.config = config
        try:
            self.fnpats = config.getini("python_files")
        except ValueError:
            self.fnpats = ["test_*.py", "*_test.py"]
        self.session = None
        self._rewritten_names = set()
        self._must_rewrite = set()
        # flag to guard against trying to rewrite a pyc file while we are already writing another pyc file,
        # which might result in infinite recursion (#3506)
        self._writing_pyc = False
        self._basenames_to_check_rewrite = {"conftest"}
        self._marked_for_rewrite_cache = {}
        self._session_paths_checked = False

    def set_session(self, session):
        self.session = session
        self._session_paths_checked = False

    # Indirection so we can mock calls to find_spec originated from the hook during testing
    _find_spec = importlib.machinery.PathFinder.find_spec

    def find_spec(self, name, path=None, target=None):
        if self._writing_pyc:
            return None
        state = self.config._assertstate
        if self._early_rewrite_bailout(name, state):
            return None
        state.trace("find_module called for: %s" % name)

        spec = self._find_spec(name, path)
        if (
            # the import machinery could not find a file to import
            spec is None
            # this is a namespace package (without `__init__.py`)
            # there's nothing to rewrite there
            # python3.5 - python3.6: `namespace`
            # python3.7+: `None`
            or spec.origin in {None, "namespace"}
            # if the file doesn't exist, we can't rewrite it
            or not os.path.exists(spec.origin)
        ):
            return None
        else:
            fn = spec.origin

        if not self._should_rewrite(name, fn, state):
            return None

        return importlib.util.spec_from_file_location(
            name,
            fn,
            loader=self,
            submodule_search_locations=spec.submodule_search_locations,
        )

    def create_module(self, spec):
        return None  # default behaviour is fine<commit_msg>Do not attempt to rewrite non-source files (#5490)<commit_after>"""Rewrite assertion AST to produce nice error messages"""
import ast
import errno
import importlib.machinery
import importlib.util
import itertools
import marshal
import os
import struct
import sys
import types

import atomicwrites

from _pytest._io.saferepr import saferepr
from _pytest._version import version
from _pytest.assertion import util
from _pytest.assertion.util import (  # noqa: F401
    format_explanation as _format_explanation,
)
from _pytest.pathlib import fnmatch_ex
from _pytest.pathlib import PurePath

# pytest caches rewritten pycs in __pycache__.
PYTEST_TAG = "{}-pytest-{}".format(sys.implementation.cache_tag, version)
PYC_EXT = ".py" + (__debug__ and "c" or "o")
PYC_TAIL = "." + PYTEST_TAG + PYC_EXT


class AssertionRewritingHook:
    """PEP302/PEP451 import hook which rewrites asserts."""

    def __init__(self, config):
        self.config = config
        try:
            self.fnpats = config.getini("python_files")
        except ValueError:
            self.fnpats = ["test_*.py", "*_test.py"]
        self.session = None
        self._rewritten_names = set()
        self._must_rewrite = set()
        # flag to guard against trying to rewrite a pyc file while we are already writing another pyc file,
        # which might result in infinite recursion (#3506)
        self._writing_pyc = False
        self._basenames_to_check_rewrite = {"conftest"}
        self._marked_for_rewrite_cache = {}
        self._session_paths_checked = False

    def set_session(self, session):
        self.session = session
        self._session_paths_checked = False

    # Indirection so we can mock calls to find_spec originated from the hook during testing
    _find_spec = importlib.machinery.PathFinder.find_spec

    def find_spec(self, name, path=None, target=None):
        if self._writing_pyc:
            return None
        state = self.config._assertstate
        if self._early_rewrite_bailout(name, state):
            return None
        state.trace("find_module called for: %s" % name)

        spec = self._find_spec(name, path)
        if (
            # the import machinery could not find a file to import
            spec is None
            # this is a namespace package (without `__init__.py`)
            # there's nothing to rewrite there
            # python3.5 - python3.6: `namespace`
            # python3.7+: `None`
            or spec.origin in {None, "namespace"}
            # we can only rewrite source files
            or not isinstance(spec.loader, importlib.machinery.SourceFileLoader)
            # if the file doesn't exist, we can't rewrite it
            or not os.path.exists(spec.origin)
        ):
            return None
        else:
            fn = spec.origin

        if not self._should_rewrite(name, fn, state):
            return None

        return importlib.util.spec_from_file_location(
            name,
            fn,
            loader=self,
            submodule_search_locations=spec.submodule_search_locations,
        )

    def create_module(self, spec):
        return None  # default behaviour is fine
{'fraction_non_alphanumeric': 0.07787351650138188, 'fraction_numerical': 0.0068281580230856774, 'mean_word_length': 2.5094124358243013, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7567324', 'n_tokens_mistral': 1828, 'n_tokens_neox': 1751, 'n_words': 532}