<commit_before># -*- coding: utf-8 -*-

"""Documentation Builder Environments."""

import logging
import os
import re
import socket
import subprocess
import sys
import traceback
from datetime import datetime

from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from docker import APIClient
from docker.errors import APIError as DockerAPIError
from docker.errors import DockerException
from requests.exceptions import ConnectionError
from requests_toolbelt.multipart.encoder import MultipartEncoder
from slumber.exceptions import HttpClientError

from readthedocs.builds.constants import BUILD_STATE_FINISHED
from readthedocs.builds.models import BuildCommandResultMixin
from readthedocs.core.utils import slugify
from readthedocs.projects.constants import LOG_TEMPLATE
from readthedocs.projects.models import Feature
from readthedocs.restapi.client import api as api_v2

from .constants import (
    DOCKER_HOSTNAME_MAX_LEN,
    DOCKER_IMAGE,
    DOCKER_LIMITS,
    DOCKER_OOM_EXIT_CODE,
    DOCKER_SOCKET,
    DOCKER_TIMEOUT_EXIT_CODE,
    DOCKER_VERSION,
)
from .exceptions import (
    BuildEnvironmentCreationFailed,
    BuildEnvironmentError,
    BuildEnvironmentException,
    BuildEnvironmentWarning,
    BuildTimeoutError,
    MkDocsYAMLParseError,
    ProjectBuildsSkippedError,
    VersionLockedError,
    YAMLParseError,
)


log = logging.getLogger(__name__)

__all__ = (
    'api_v2',
    'BuildCommand',
    'DockerBuildCommand',
    'LocalEnvironment',
    'LocalBuildEnvironment',
    'DockerBuildEnvironment',
)


class BuildCommand(BuildCommandResultMixin):

    """
    Wrap command execution for execution in build environments.

    This wraps subprocess commands with some logic to handle exceptions,
    logging, and setting up the env for the build command.

    This acts a mapping of sorts to the API representation of the
    :py:class:`readthedocs.builds.models.BuildCommandResult` model.

    :param command: string or array of command parameters
    :param cwd: current working path for the command
    :param shell: execute command in shell, default=False
    :param environment: environment variables to add to environment
    :type environment: dict
    :param combine_output: combine stdout/stderr, default=True
    :param input_data: data to pass in on stdin
    :type input_data: str
    :param build_env: build environment to use to execute commands
    :param bin_path: binary path to add to PATH resolution
    :param description: a more grokable description of the command being run
    """

    def __init__(
            self,
            command,
            cwd=None,
            shell=False,
            environment=None,
            combine_output=True,
            input_data=None,
            build_env=None,
            bin_path=None,
            description=None,
            record_as_success=False,
    ):
        self.command = command
        self.shell = shell<commit_msg>Allow to extend BuildCommand class with **kwargs<commit_after># -*- coding: utf-8 -*-

"""Documentation Builder Environments."""

import logging
import os
import re
import socket
import subprocess
import sys
import traceback
from datetime import datetime

from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from docker import APIClient
from docker.errors import APIError as DockerAPIError
from docker.errors import DockerException
from requests.exceptions import ConnectionError
from requests_toolbelt.multipart.encoder import MultipartEncoder
from slumber.exceptions import HttpClientError

from readthedocs.builds.constants import BUILD_STATE_FINISHED
from readthedocs.builds.models import BuildCommandResultMixin
from readthedocs.core.utils import slugify
from readthedocs.projects.constants import LOG_TEMPLATE
from readthedocs.projects.models import Feature
from readthedocs.restapi.client import api as api_v2

from .constants import (
    DOCKER_HOSTNAME_MAX_LEN,
    DOCKER_IMAGE,
    DOCKER_LIMITS,
    DOCKER_OOM_EXIT_CODE,
    DOCKER_SOCKET,
    DOCKER_TIMEOUT_EXIT_CODE,
    DOCKER_VERSION,
)
from .exceptions import (
    BuildEnvironmentCreationFailed,
    BuildEnvironmentError,
    BuildEnvironmentException,
    BuildEnvironmentWarning,
    BuildTimeoutError,
    MkDocsYAMLParseError,
    ProjectBuildsSkippedError,
    VersionLockedError,
    YAMLParseError,
)


log = logging.getLogger(__name__)

__all__ = (
    'api_v2',
    'BuildCommand',
    'DockerBuildCommand',
    'LocalEnvironment',
    'LocalBuildEnvironment',
    'DockerBuildEnvironment',
)


class BuildCommand(BuildCommandResultMixin):

    """
    Wrap command execution for execution in build environments.

    This wraps subprocess commands with some logic to handle exceptions,
    logging, and setting up the env for the build command.

    This acts a mapping of sorts to the API representation of the
    :py:class:`readthedocs.builds.models.BuildCommandResult` model.

    :param command: string or array of command parameters
    :param cwd: current working path for the command
    :param shell: execute command in shell, default=False
    :param environment: environment variables to add to environment
    :type environment: dict
    :param combine_output: combine stdout/stderr, default=True
    :param input_data: data to pass in on stdin
    :type input_data: str
    :param build_env: build environment to use to execute commands
    :param bin_path: binary path to add to PATH resolution
    :param description: a more grokable description of the command being run
    :param kwargs: allow to subclass this class and extend it
    """

    def __init__(
            self,
            command,
            cwd=None,
            shell=False,
            environment=None,
            combine_output=True,
            input_data=None,
            build_env=None,
            bin_path=None,
            description=None,
            record_as_success=False,
            **kwargs,
    ):
        self.command = command
        self.shell = shell
{'fraction_non_alphanumeric': 0.055105080258149926, 'fraction_numerical': 0.0009928843289756743, 'mean_word_length': 3.592705167173252, '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': '117356', 'n_tokens_mistral': 1665, 'n_tokens_neox': 1630, 'n_words': 528}