<commit_before>import os
from traitlets import Any, Unicode, default

from jupyterhub.spawner import LocalProcessSpawner
from jupyterhub import orm


class Spawner(LocalProcessSpawner):
    #: The instance of the orm Proxy.
    #: We use Any in agreement with base class practice.
    proxy = Any()

    #: The path of the configuration file for the cmd executable
    config_file_path = Unicode()

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        # We get the first one. Strangely enough, jupyterhub has a table
        # containing potentially multiple proxies, but it's enforced to
        # contain only one.
        self.proxy = self.db.query(orm.Proxy).first()
        self.cmd = ['remoteappmanager']

    def get_args(self):
        args = super().get_args()
        args.append("--proxy-api-url={}".format(self.proxy.api_server.url))
        args.append("--config-file={}".format(self.config_file_path))
        return args

    def get_env(self):
        env = super().get_env()
        env["PROXY_API_TOKEN"] = self.proxy.auth_token
        return env

    @default("config_file_path")
    def _config_file_path_default(self):
        """Defines the default position of the configuration file for
        our utility. By default, it's the cwd of where we started up."""
        return os.path.join(os.getcwd(),
                            os.path.basename(self.cmd[0])+'_config.py')<commit_msg>Added VirtualUserSpawner<commit_after>import os
import shutil
import tempfile

from traitlets import Any, Unicode, Bool, default
from tornado import gen

from jupyterhub.spawner import LocalProcessSpawner
from jupyterhub import orm


class Spawner(LocalProcessSpawner):
    #: The instance of the orm Proxy.
    #: We use Any in agreement with base class practice.
    proxy = Any()

    #: The path of the configuration file for the cmd executable
    config_file_path = Unicode()

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        # We get the first one. Strangely enough, jupyterhub has a table
        # containing potentially multiple proxies, but it's enforced to
        # contain only one.
        self.proxy = self.db.query(orm.Proxy).first()
        self.cmd = ['remoteappmanager']

    def get_args(self):
        args = super().get_args()
        args.append("--proxy-api-url={}".format(self.proxy.api_server.url))
        args.append("--config-file={}".format(self.config_file_path))
        return args

    def get_env(self):
        env = super().get_env()
        env["PROXY_API_TOKEN"] = self.proxy.auth_token
        return env

    @default("config_file_path")
    def _config_file_path_default(self):
        """Defines the default position of the configuration file for
        our utility. By default, it's the cwd of where we started up."""
        return os.path.join(os.getcwd(),
                            os.path.basename(self.cmd[0])+'_config.py')


class VirtualUserSpawner(LocalProcessSpawner):
    #: The instance of the orm Proxy.
    #: We use Any in agreement with base class practice.
    proxy = Any()

    #: The path of the configuration file for the cmd executable
    config_file_path = Unicode(config=True)

    #: Directory in which temporary home directory for the virtual
    #: user is created.  No directory is created if this is not
    #: defined.
    workspace_dir = Unicode(config=True)

    #: The path to the temporary workspace directory
    _virtual_workspace = Unicode()

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        # We get the first one. Strangely enough, jupyterhub has a table
        # containing potentially multiple proxies, but it's enforced to
        # contain only one.
        self.proxy = self.db.query(orm.Proxy).first()
        self.cmd = ['remoteappmanager']

    def make_preexec_fn(self, name):
        # We don't set user uid for virtual user
        # Nor do we try to start the process in the user's
        # home directory (it does not exist)
        pass

    def load_state(self, state):
        super().load_state(state)
        virtual_workspace = state.get('virtual_workspace')
        if virtual_workspace and os.path.isdir(virtual_workspace):
            self._virtual_workspace = virtual_workspace

    def get_state(self):
        state = super().get_state()
        if self._virtual_workspace:
            state['virtual_workspace'] = self._virtual_workspace
        return state

    def clear_state(self):
        super().clear_state()
        self._virtual_workspace = ''

    def get_args(self):
        args = super().get_args()
        args.append("--proxy-api-url={}".format(self.proxy.api_server.url))
        args.append("--config-file={}".format(self.config_file_path))
        return args

    def user_env(self, env):
        env['USER'] = self.user.name

        if self.workspace_dir:
            if not self._virtual_workspace:
                self._virtual_workspace = tempfile.mkdtemp(
                    dir=self.workspace_dir)
                self.log.info("Created temporary directory: %s",
                              self._virtual_workspace)

            env['HOME'] = self._virtual_workspace

        return env

    def get_env(self):
        # LocalProcessSpawner.get_env calls user_env as well
        env = super().get_env()
        env["PROXY_API_TOKEN"] = self.proxy.auth_token
        return env

    @gen.coroutine
    def stop(self, now=False):
        """ Stop the process

        If virtual user has a temporary home directory,
        clean up the directory.
        """
        # Clean up the directory
        if self._virtual_workspace:
            # Make sure the temporary directory is not /, ./ or ../
            if self._virtual_workspace.strip('/') in ('', '.', '..'):
                self.log.warning("Virtual workspace is '%s'.  Seriously? "
                                 "Not removing.", self._virtual_workspace)
            else:
                self.log.info('Removing %s ...', self._virtual_workspace)

                try:
                    shutil.rmtree(self._virtual_workspace)
                except Exception as exception:
                    self.log.error("Failed to remove %s, error %s",
                                   self._virtual_workspace, str(exception))

        super().stop(now=now)
{'fraction_non_alphanumeric': 0.10163882760794202, 'fraction_numerical': 0.0003151591553734636, 'mean_word_length': 2.37068507700478, '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': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1178923', 'n_tokens_mistral': 1844, 'n_tokens_neox': 1775, 'n_words': 503}