# Path: scuba/config.py
# class ScubaConfig:
#     def __init__(self, **data):
#         optional_nodes = (
#             'image', 'aliases', 'hooks', 'entrypoint', 'environment', 'shell',
#             'docker_args', 'volumes',
#         )
# 
#         # Check for unrecognized nodes
#         extra = [n for n in data if not n in optional_nodes]
#         if extra:
#             raise ConfigError('{}: Unrecognized node{}: {}'.format(SCUBA_YML,
#                     's' if len(extra) > 1 else '', ', '.join(extra)))
# 
#         self._image = data.get('image')
#         self.shell = data.get('shell', DEFAULT_SHELL)
#         self.entrypoint = _get_entrypoint(data)
#         self.docker_args = _get_docker_args(data)
#         self.volumes = _get_volumes(data)
#         self._load_aliases(data)
#         self._load_hooks(data)
#         self._load_environment(data)
# 
# 
#     def _load_aliases(self, data):
#         self.aliases = {}
# 
#         for name, node in data.get('aliases', {}).items():
#             if ' ' in name:
#                 raise ConfigError('Alias names cannot contain spaces')
#             self.aliases[name] = ScubaAlias.from_dict(name, node)
# 
#     def _load_hooks(self, data):
#         self.hooks = {}
# 
#         for name in ('user', 'root',):
#             node = data.get('hooks', {}).get(name)
#             if node:
#                 hook = _process_script_node(node, name)
#                 self.hooks[name] = hook
# 
#     def _load_environment(self, data):
#         self.environment = _process_environment(data.get('environment'), 'environment')
# 
# 
#     @property
#     def image(self):
#         if not self._image:
#             raise ConfigError("Top-level 'image' not set")
#         return self._image
# 
# class ConfigError(Exception):
#     pass
# 
# class OverrideStr(str, OverrideMixin):
#     pass
# 
# Path: scuba/scuba.py
# class ScubaContext:
#     def __init__(self, image=None, script=None, entrypoint=None, environment=None, shell=None, docker_args=None, volumes=None):
#         self.image = image
#         self.script = script
#         self.as_root = False
#         self.entrypoint = entrypoint
#         self.environment = environment
#         self.shell = shell
#         self.docker_args = docker_args
#         self.volumes = volumes or {}
# 
#     @classmethod
#     def process_command(cls, cfg, command, image=None, shell=None):
#         '''Processes a user command using aliases
# 
#         Arguments:
#             cfg         ScubaConfig object
#             command     A user command list (e.g. argv)
#             image       Override the image from .scuba.yml
#             shell       Override the shell from .scuba.yml
# 
#         Returns: A ScubaContext object with the following attributes:
#             script: a list of command line strings
#             image: the docker image name to use
#         '''
#         result = cls(
#                 entrypoint = cfg.entrypoint,
#                 environment = cfg.environment.copy(),
#                 shell = cfg.shell,
#                 docker_args = cfg.docker_args,
#                 volumes = cfg.volumes,
#                 )
# 
#         if command:
#             alias = cfg.aliases.get(command[0])
#             if not alias:
#                 # Command is not an alias; use it as-is.
#                 result.script = [shell_quote_cmd(command)]
#             else:
#                 # Using an alias
#                 # Does this alias override the image and/or entrypoint?
#                 if alias.image:
#                     result.image = alias.image
#                 if alias.entrypoint is not None:
#                     result.entrypoint = alias.entrypoint
#                 if alias.shell is not None:
#                     result.shell = alias.shell
#                 if alias.as_root:
#                     result.as_root = True
# 
#                 if isinstance(alias.docker_args, OverrideMixin) or result.docker_args is None:
#                     result.docker_args = alias.docker_args
#                 elif alias.docker_args is not None:
#                     result.docker_args.extend(alias.docker_args)
# 
#                 if alias.volumes is not None:
#                     result.volumes.update(alias.volumes)
# 
#                 # Merge/override the environment
#                 if alias.environment:
#                     result.environment.update(alias.environment)
# 
#                 if len(alias.script) > 1:
#                     # Alias is a multiline script; no additional
#                     # arguments are allowed in the scuba invocation.
#                     if len(command) > 1:
#                         raise ConfigError('Additional arguments not allowed with multi-line aliases')
#                     result.script = alias.script
# 
#                 else:
#                     # Alias is a single-line script; perform substituion
#                     # and add user arguments.
#                     command.pop(0)
#                     result.script = [alias.script[0] + ' ' + shell_quote_cmd(command)]
# 
#             result.script = flatten_list(result.script)
# 
#         # If a shell was given on the CLI, it should override the shell set by
#         # the alias or top-level config
#         if shell:
#             result.shell = shell
# 
#         # If an image was given, it overrides what might have been set by an alias
#         if image:
#             result.image = image
# 
#         # If the image was still not set, then try to get it from the confg,
#         # which will raise a ConfigError if it is not set
#         if not result.image:
#             result.image = cfg.image
# 
#         return result


import pytest
import shlex
from scuba.config import ScubaConfig, ConfigError, OverrideStr
from scuba.scuba import ScubaContext


class TestScubaContext:
    def test_process_command_image(self):
        '''process_command returns the image and entrypoint'''
        image_name = 'test_image'
        entrypoint = 'test_entrypoint'

        cfg = ScubaConfig(
                image = image_name,
                entrypoint = entrypoint,
                )
        result = ScubaContext.process_command(cfg, [])
        assert result.image == image_name
        assert result.entrypoint == entrypoint

    def test_process_command_empty(self):
        '''process_command handles no aliases and an empty command'''
        cfg = ScubaConfig(
                image = 'na',
                )
        result = ScubaContext.process_command(cfg, [])
        assert result.script == None


    def test_process_command_no_aliases(self):
        '''process_command handles no aliases'''

# Path: scuba/config.py
# class ScubaConfig:
#     def __init__(self, **data):
#         optional_nodes = (
#             'image', 'aliases', 'hooks', 'entrypoint', 'environment', 'shell',
#             'docker_args', 'volumes',
#         )
# 
#         # Check for unrecognized nodes
#         extra = [n for n in data if not n in optional_nodes]
#         if extra:
#             raise ConfigError('{}: Unrecognized node{}: {}'.format(SCUBA_YML,
#                     's' if len(extra) > 1 else '', ', '.join(extra)))
# 
#         self._image = data.get('image')
#         self.shell = data.get('shell', DEFAULT_SHELL)
#         self.entrypoint = _get_entrypoint(data)
#         self.docker_args = _get_docker_args(data)
#         self.volumes = _get_volumes(data)
#         self._load_aliases(data)
#         self._load_hooks(data)
#         self._load_environment(data)
# 
# 
#     def _load_aliases(self, data):
#         self.aliases = {}
# 
#         for name, node in data.get('aliases', {}).items():
#             if ' ' in name:
#                 raise ConfigError('Alias names cannot contain spaces')
#             self.aliases[name] = ScubaAlias.from_dict(name, node)
# 
#     def _load_hooks(self, data):
#         self.hooks = {}
# 
#         for name in ('user', 'root',):
#             node = data.get('hooks', {}).get(name)
#             if node:
#                 hook = _process_script_node(node, name)
#                 self.hooks[name] = hook
# 
#     def _load_environment(self, data):
#         self.environment = _process_environment(data.get('environment'), 'environment')
# 
# 
#     @property
#     def image(self):
#         if not self._image:
#             raise ConfigError("Top-level 'image' not set")
#         return self._image
# 
# class ConfigError(Exception):
#     pass
# 
# class OverrideStr(str, OverrideMixin):
#     pass
# 
# Path: scuba/scuba.py
# class ScubaContext:
#     def __init__(self, image=None, script=None, entrypoint=None, environment=None, shell=None, docker_args=None, volumes=None):
#         self.image = image
#         self.script = script
#         self.as_root = False
#         self.entrypoint = entrypoint
#         self.environment = environment
#         self.shell = shell
#         self.docker_args = docker_args
#         self.volumes = volumes or {}
# 
#     @classmethod
#     def process_command(cls, cfg, command, image=None, shell=None):
#         '''Processes a user command using aliases
# 
#         Arguments:
#             cfg         ScubaConfig object
#             command     A user command list (e.g. argv)
#             image       Override the image from .scuba.yml
#             shell       Override the shell from .scuba.yml
# 
#         Returns: A ScubaContext object with the following attributes:
#             script: a list of command line strings
#             image: the docker image name to use
#         '''
#         result = cls(
#                 entrypoint = cfg.entrypoint,
#                 environment = cfg.environment.copy(),
#                 shell = cfg.shell,
#                 docker_args = cfg.docker_args,
#                 volumes = cfg.volumes,
#                 )
# 
#         if command:
#             alias = cfg.aliases.get(command[0])
#             if not alias:
#                 # Command is not an alias; use it as-is.
#                 result.script = [shell_quote_cmd(command)]
#             else:
#                 # Using an alias
#                 # Does this alias override the image and/or entrypoint?
#                 if alias.image:
#                     result.image = alias.image
#                 if alias.entrypoint is not None:
#                     result.entrypoint = alias.entrypoint
#                 if alias.shell is not None:
#                     result.shell = alias.shell
#                 if alias.as_root:
#                     result.as_root = True
# 
#                 if isinstance(alias.docker_args, OverrideMixin) or result.docker_args is None:
#                     result.docker_args = alias.docker_args
#                 elif alias.docker_args is not None:
#                     result.docker_args.extend(alias.docker_args)
# 
#                 if alias.volumes is not None:
#                     result.volumes.update(alias.volumes)
# 
#                 # Merge/override the environment
#                 if alias.environment:
#                     result.environment.update(alias.environment)
# 
#                 if len(alias.script) > 1:
#                     # Alias is a multiline script; no additional
#                     # arguments are allowed in the scuba invocation.
#                     if len(command) > 1:
#                         raise ConfigError('Additional arguments not allowed with multi-line aliases')
#                     result.script = alias.script
# 
#                 else:
#                     # Alias is a single-line script; perform substituion
#                     # and add user arguments.
#                     command.pop(0)
#                     result.script = [alias.script[0] + ' ' + shell_quote_cmd(command)]
# 
#             result.script = flatten_list(result.script)
# 
#         # If a shell was given on the CLI, it should override the shell set by
#         # the alias or top-level config
#         if shell:
#             result.shell = shell
# 
#         # If an image was given, it overrides what might have been set by an alias
#         if image:
#             result.image = image
# 
#         # If the image was still not set, then try to get it from the confg,
#         # which will raise a ConfigError if it is not set
#         if not result.image:
#             result.image = cfg.image
# 
#         return result


# Path: tests/test_scuba.py
import pytest
import shlex
from scuba.config import ScubaConfig, ConfigError, OverrideStr
from scuba.scuba import ScubaContext



class TestScubaContext:
    def test_process_command_image(self):
        '''process_command returns the image and entrypoint'''
        image_name = 'test_image'
        entrypoint = 'test_entrypoint'

        cfg = ScubaConfig(
                image = image_name,
                entrypoint = entrypoint,
                )
        result = ScubaContext.process_command(cfg, [])
        assert result.image == image_name
        assert result.entrypoint == entrypoint

    def test_process_command_empty(self):
        '''process_command handles no aliases and an empty command'''
        cfg = ScubaConfig(
                image = 'na',
                )
        result = ScubaContext.process_command(cfg, [])
        assert result.script == None


    def test_process_command_no_aliases(self):
        '''process_command handles no aliases'''

        cfg = ScubaConfig(