<commit_before>
import contextlib
import logging
import os
import paramiko
import random
import socket
import termcolor
import time
from stat import S_ISDIR, S_ISREG

from deployer.console import Console
from deployer.exceptions import ExecCommandFailed
from deployer.loggers import DummyLoggerInterface
from deployer.pseudo_terminal import DummyPty, select
from deployer.std import raw_mode
from deployer.utils import esc1

from StringIO import StringIO
from twisted.internet import fdesc

__all__ = (
    'Host',
    'HostContext',
    'Stat',
)

class HostContext(object):
    """
    A push/pop stack which keeps track of the context on which commands
    at a host are executed.

    (This is mainly used internally by the library.)
    """
        # TODO: Guarantee thread safety!! When doing parallel deployments, and
        #       several threads act on the same host, things will probably go
        #       wrong...
    def __init__(self):
        self._command_prefixes = []
        self._path = []
        self._env = []

    def copy(self):
        """ Create a deep copy. """
        c = HostContext()
        c._command_prefixes = list(self._command_prefixes)
        c._path = list(self._path)
        c._env = list(self._env)
        return c

    def __repr__(self):
        return 'HostContext(prefixes=%r, path=%r, env=%r)' % (
                        self._command_prefixes, self._path, self._env)

    def prefix(self, command):
        """
        Prefix all commands with given command plus ``&&``.

        ::

            with host.prefix('workon environment'):
                host.run('./manage.py migrate')
        """
        class Prefix(object):
            def __enter__(context):
                self._command_prefixes.append(command)

            def __exit__(context, *args):
                self._command_prefixes.pop()
        return Prefix()

    def cd(self, path, expand=False):
        """
        Execute commands in this directory. Nesting of cd-statements is
        allowed.

        ::

            with host.cd('directory'):
                host.run('ls')

        :param expand: Expand tildes.
        :type expand: bool
        """
        class CD(object):
            def __enter__(context):
                self._path.append((path, expand))

            def __exit__(context, *args):
                self._path.pop()
        return CD()

    def _chdir(self, path):
        """ Move to this directory. Not to be used together with the `cd` context manager. """
        # NOTE: This is used by the sftp shell.
        self._path = [ (os.path.join(* self._path + [path]), False) ]

    def env(self, variable, value, escape=True):
        """<commit_msg>Fix for HostContext._chdir. Fixes the scp shell.<commit_after>
import contextlib
import logging
import os
import paramiko
import random
import socket
import termcolor
import time
from stat import S_ISDIR, S_ISREG

from deployer.console import Console
from deployer.exceptions import ExecCommandFailed
from deployer.loggers import DummyLoggerInterface
from deployer.pseudo_terminal import DummyPty, select
from deployer.std import raw_mode
from deployer.utils import esc1

from StringIO import StringIO
from twisted.internet import fdesc

__all__ = (
    'Host',
    'HostContext',
    'Stat',
)

class HostContext(object):
    """
    A push/pop stack which keeps track of the context on which commands
    at a host are executed.

    (This is mainly used internally by the library.)
    """
        # TODO: Guarantee thread safety!! When doing parallel deployments, and
        #       several threads act on the same host, things will probably go
        #       wrong...
    def __init__(self):
        self._command_prefixes = []
        self._path = []
        self._env = []

    def copy(self):
        """ Create a deep copy. """
        c = HostContext()
        c._command_prefixes = list(self._command_prefixes)
        c._path = list(self._path)
        c._env = list(self._env)
        return c

    def __repr__(self):
        return 'HostContext(prefixes=%r, path=%r, env=%r)' % (
                        self._command_prefixes, self._path, self._env)

    def prefix(self, command):
        """
        Prefix all commands with given command plus ``&&``.

        ::

            with host.prefix('workon environment'):
                host.run('./manage.py migrate')
        """
        class Prefix(object):
            def __enter__(context):
                self._command_prefixes.append(command)

            def __exit__(context, *args):
                self._command_prefixes.pop()
        return Prefix()

    def cd(self, path, expand=False):
        """
        Execute commands in this directory. Nesting of cd-statements is
        allowed.

        ::

            with host.cd('directory'):
                host.run('ls')

        :param expand: Expand tildes.
        :type expand: bool
        """
        class CD(object):
            def __enter__(context):
                self._path.append((path, expand))

            def __exit__(context, *args):
                self._path.pop()
        return CD()

    def _chdir(self, path):
        """ Move to this directory. Not to be used together with the `cd` context manager. """
        # NOTE: This is used by the sftp shell.
        # TODO: check 'expand' flags.
        self._path = [ (os.path.join(* [p[0] for p in self._path] + [path]), False) ]

    def env(self, variable, value, escape=True):
        """
{'fraction_non_alphanumeric': 0.09994548428130111, 'fraction_numerical': 0.0005451571869889151, 'mean_word_length': 2.145142857142857, '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': '2058482', 'n_tokens_mistral': 1542, 'n_tokens_neox': 1477, 'n_words': 482}