<commit_before># -*- coding: utf-8 -*-
import builtins
import logging
import os
import shlex
import stat
import sys
from collections import namedtuple
from contextlib import contextmanager
from distutils.util import strtobool
from glob import glob
from importlib import reload
from importlib.util import find_spec
from os import environ
from os.path import isdir
from os.path import join as path_join
from pprint import pformat
from shutil import rmtree, which
from time import sleep

from pkg_resources import DistributionNotFound

import pytest

from .helpers import uniqstr


def nop(*args, **kwargs):
    """Function that does nothing"""


def obj(**kwargs):
    """Create a generic object with the given fields"""
    constructor = namedtuple("GenericObject", kwargs.keys())
    return constructor(**kwargs)


def set_writable(func, path, exc_info):
    max_attempts = 10
    retry_interval = 0.1
    effective_ids = os.access in os.supports_effective_ids
    existing_files = glob("{}/*".format(path))

    if not os.access(path, os.W_OK, effective_ids=effective_ids):
        os.chmod(path, stat.S_IWUSR)
        return func(path)
    else:
        # For some weird reason we do have rights to remove the dir,
        # let's try again a few times more slowly (maybe a previous OS call
        # returned to the python interpreter but the files were not completely
        # removed yet?)
        for i in range(max_attempts):
            try:
                return rmtree(path)
            except OSError:
                sleep((i + 1) * retry_interval)

    logging.critical(
        "Something went wrong when removing %s. Contents:\n%s",
        path,
        pformat(existing_files),  # weirdly this is usually empty
        exc_info=exc_info,
    )
    (type_, value, traceback) = exc_info
    raise type_(value).with_traceback(traceback)


def command_exception(content):
    # Be lazy to import modules, so coverage has time to setup all the
    # required "probes"
    # (see @FlorianWilhelm comments on #174)
    from pyscaffold.exceptions import ShellCommandException

    return ShellCommandException(content)


def _config_git(home):
    config = """
        [user]
          name = <NAME>
          email = <EMAIL>
    """
    (home / ".gitconfig").write_text(config)


def _fake_expanduser(original_expand, fake_home):
    original_home = str(original_expand("~"))

    def _expand(path):
        value = original_expand(path)
        return value.replace(original_home, str(fake_home))

    return _expand


@pytest.fixture(autouse=True)
def fake_home(tmp_path, monkeypatch):
    """Isolate tests.
    Avoid interference of an existing config dir in the developer's
    machine
    """
    fake = tmp_path / ("home" + uniqstr())
    fake.mkdir()
    _config_git(fake)

    original_expand = os.path.expanduser
    monkeypatch.setattr(
        "os.path.expanduser", _fake_expanduser(original_expand, fake)
    )
    monkeypatch.setenv("HOME", str(fake))
    monkeypatch.setenv("USERPROFILE", str(fake))  # Windows?

    yield fake<commit_msg>Fix conftest format with black<commit_after># -*- coding: utf-8 -*-
import builtins
import logging
import os
import shlex
import stat
import sys
from collections import namedtuple
from contextlib import contextmanager
from distutils.util import strtobool
from glob import glob
from importlib import reload
from importlib.util import find_spec
from os import environ
from os.path import isdir
from os.path import join as path_join
from pprint import pformat
from shutil import rmtree, which
from time import sleep

from pkg_resources import DistributionNotFound

import pytest

from .helpers import uniqstr


def nop(*args, **kwargs):
    """Function that does nothing"""


def obj(**kwargs):
    """Create a generic object with the given fields"""
    constructor = namedtuple("GenericObject", kwargs.keys())
    return constructor(**kwargs)


def set_writable(func, path, exc_info):
    max_attempts = 10
    retry_interval = 0.1
    effective_ids = os.access in os.supports_effective_ids
    existing_files = glob("{}/*".format(path))

    if not os.access(path, os.W_OK, effective_ids=effective_ids):
        os.chmod(path, stat.S_IWUSR)
        return func(path)
    else:
        # For some weird reason we do have rights to remove the dir,
        # let's try again a few times more slowly (maybe a previous OS call
        # returned to the python interpreter but the files were not completely
        # removed yet?)
        for i in range(max_attempts):
            try:
                return rmtree(path)
            except OSError:
                sleep((i + 1) * retry_interval)

    logging.critical(
        "Something went wrong when removing %s. Contents:\n%s",
        path,
        pformat(existing_files),  # weirdly this is usually empty
        exc_info=exc_info,
    )
    (type_, value, traceback) = exc_info
    raise type_(value).with_traceback(traceback)


def command_exception(content):
    # Be lazy to import modules, so coverage has time to setup all the
    # required "probes"
    # (see @FlorianWilhelm comments on #174)
    from pyscaffold.exceptions import ShellCommandException

    return ShellCommandException(content)


def _config_git(home):
    config = """
        [user]
          name = <NAME>
          email = <EMAIL>
    """
    (home / ".gitconfig").write_text(config)


def _fake_expanduser(original_expand, fake_home):
    original_home = str(original_expand("~"))

    def _expand(path):
        value = original_expand(path)
        return value.replace(original_home, str(fake_home))

    return _expand


@pytest.fixture(autouse=True)
def fake_home(tmp_path, monkeypatch):
    """Isolate tests.
    Avoid interference of an existing config dir in the developer's
    machine
    """
    fake = tmp_path / ("home" + uniqstr())
    fake.mkdir()
    _config_git(fake)

    original_expand = os.path.expanduser
    monkeypatch.setattr("os.path.expanduser", _fake_expanduser(original_expand, fake))
    monkeypatch.setenv("HOME", str(fake))
    monkeypatch.setenv("USERPROFILE", str(fake))  # Windows?

    yield fake
{'fraction_non_alphanumeric': 0.08935268221098973, 'fraction_numerical': 0.0029349421164193705, 'mean_word_length': 3.233264320220842, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, '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': '3347089', 'n_tokens_mistral': 1841, 'n_tokens_neox': 1774, 'n_words': 566}