Keep no-ansi parameter in the CLI scope

Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
Joffrey F 2017-08-09 16:46:47 -07:00 committed by Joffrey F
parent 444d888720
commit 7882f1fb06
7 changed files with 50 additions and 40 deletions

View File

@ -31,7 +31,6 @@ def project_from_options(project_dir, options):
get_config_path_from_options(project_dir, options, environment),
project_name=options.get('--project-name'),
verbose=options.get('--verbose'),
noansi=options.get('--no-ansi'),
host=host,
tls_config=tls_config_from_options(options),
environment=environment,
@ -82,7 +81,7 @@ def get_client(environment, verbose=False, version=None, tls_config=None, host=N
def get_project(project_dir, config_path=None, project_name=None, verbose=False,
noansi=False, host=None, tls_config=None, environment=None, override_dir=None):
host=None, tls_config=None, environment=None, override_dir=None):
if not environment:
environment = Environment.from_env_file(project_dir)
config_details = config.find(project_dir, config_path, environment, override_dir)
@ -101,7 +100,7 @@ def get_project(project_dir, config_path=None, project_name=None, verbose=False,
)
with errors.handle_connection_errors(client):
return Project.from_config(project_name, config_data, client, noansi=noansi)
return Project.from_config(project_name, config_data, client)
def get_project_name(working_dir, project_name=None, environment=None):

View File

@ -98,6 +98,7 @@ def dispatch():
options, handler, command_options = dispatcher.parse(sys.argv[1:])
setup_console_handler(console_handler, options.get('--verbose'))
setup_parallel_logger(options.get('--no-ansi'))
return functools.partial(perform_command, options, handler, command_options)
@ -127,6 +128,12 @@ def setup_logging():
logging.getLogger("requests").propagate = False
def setup_parallel_logger(noansi):
if noansi:
import compose.parallel
compose.parallel.ParallelStreamWriter.set_noansi()
def setup_console_handler(handler, verbose):
if handler.stream.isatty():
format_class = ConsoleWarningFormatter

View File

@ -26,7 +26,7 @@ log = logging.getLogger(__name__)
STOP = object()
def parallel_execute(objects, func, get_name, msg, get_deps=None, limit=None, noansi=False):
def parallel_execute(objects, func, get_name, msg, get_deps=None, limit=None):
"""Runs func on objects in parallel while ensuring that func is
ran on object only after it is ran on all its dependencies.
@ -36,7 +36,7 @@ def parallel_execute(objects, func, get_name, msg, get_deps=None, limit=None, no
objects = list(objects)
stream = get_output_stream(sys.stderr)
writer = ParallelStreamWriter(stream, msg, noansi)
writer = ParallelStreamWriter(stream, msg)
for obj in objects:
writer.add_object(get_name(obj))
writer.write_initial()
@ -221,12 +221,17 @@ class ParallelStreamWriter(object):
to jump to the correct line, and write over the line.
"""
def __init__(self, stream, msg, noansi):
noansi = False
@classmethod
def set_noansi(cls, value=True):
cls.noansi = value
def __init__(self, stream, msg):
self.stream = stream
self.msg = msg
self.lines = []
self.width = 0
self.noansi = noansi
def add_object(self, obj_index):
self.lines.append(obj_index)
@ -267,27 +272,27 @@ class ParallelStreamWriter(object):
self._write_ansi(obj_index, status)
def parallel_operation(containers, operation, options, message, noansi=False):
def parallel_operation(containers, operation, options, message):
parallel_execute(
containers,
operator.methodcaller(operation, **options),
operator.attrgetter('name'),
message,
noansi=noansi)
)
def parallel_remove(containers, options, noansi=False):
def parallel_remove(containers, options):
stopped_containers = [c for c in containers if not c.is_running]
parallel_operation(stopped_containers, 'remove', options, 'Removing', noansi=noansi)
parallel_operation(stopped_containers, 'remove', options, 'Removing')
def parallel_pause(containers, options, noansi=False):
parallel_operation(containers, 'pause', options, 'Pausing', noansi=noansi)
def parallel_pause(containers, options):
parallel_operation(containers, 'pause', options, 'Pausing')
def parallel_unpause(containers, options, noansi=False):
parallel_operation(containers, 'unpause', options, 'Unpausing', noansi=noansi)
def parallel_unpause(containers, options):
parallel_operation(containers, 'unpause', options, 'Unpausing')
def parallel_kill(containers, options, noansi=False):
parallel_operation(containers, 'kill', options, 'Killing', noansi=noansi)
def parallel_kill(containers, options):
parallel_operation(containers, 'kill', options, 'Killing')

View File

@ -60,15 +60,13 @@ class Project(object):
"""
A collection of services.
"""
def __init__(self, name, services, client, networks=None, volumes=None, config_version=None,
noansi=False):
def __init__(self, name, services, client, networks=None, volumes=None, config_version=None):
self.name = name
self.services = services
self.client = client
self.volumes = volumes or ProjectVolumes({})
self.networks = networks or ProjectNetworks({}, False)
self.config_version = config_version
self.noansi = noansi
def labels(self, one_off=OneOffFilter.exclude):
labels = ['{0}={1}'.format(LABEL_PROJECT, self.name)]
@ -77,7 +75,7 @@ class Project(object):
return labels
@classmethod
def from_config(cls, name, config_data, client, noansi=False):
def from_config(cls, name, config_data, client):
"""
Construct a Project from a config.Config object.
"""
@ -88,7 +86,7 @@ class Project(object):
networks,
use_networking)
volumes = ProjectVolumes.from_config(name, config_data, client)
project = cls(name, [], client, project_networks, volumes, config_data.version, noansi=noansi)
project = cls(name, [], client, project_networks, volumes, config_data.version)
for service_dict in config_data.services:
service_dict = dict(service_dict)
@ -128,7 +126,6 @@ class Project(object):
volumes_from=volumes_from,
secrets=secrets,
pid_mode=pid_mode,
noansi=noansi,
**service_dict)
)
@ -274,7 +271,7 @@ class Project(object):
operator.attrgetter('name'),
'Starting',
get_deps,
noansi=self.noansi)
)
return containers
@ -293,25 +290,25 @@ class Project(object):
operator.attrgetter('name'),
'Stopping',
get_deps,
noansi=self.noansi)
)
def pause(self, service_names=None, **options):
containers = self.containers(service_names)
parallel.parallel_pause(reversed(containers), options, noansi=self.noansi)
parallel.parallel_pause(reversed(containers), options)
return containers
def unpause(self, service_names=None, **options):
containers = self.containers(service_names)
parallel.parallel_unpause(containers, options, noansi=self.noansi)
parallel.parallel_unpause(containers, options)
return containers
def kill(self, service_names=None, **options):
parallel.parallel_kill(self.containers(service_names), options, noansi=self.noansi)
parallel.parallel_kill(self.containers(service_names), options)
def remove_stopped(self, service_names=None, one_off=OneOffFilter.exclude, **options):
parallel.parallel_remove(self.containers(
service_names, stopped=True, one_off=one_off
), options, noansi=self.noansi)
), options)
def down(self, remove_image_type, include_volumes, remove_orphans=False):
self.stop(one_off=OneOffFilter.include)
@ -337,7 +334,7 @@ class Project(object):
self.build_container_operation_with_timeout_func('restart', options),
operator.attrgetter('name'),
'Restarting',
noansi=self.noansi)
)
return containers
def build(self, service_names=None, no_cache=False, pull=False, force_rm=False, build_args=None):
@ -454,7 +451,6 @@ class Project(object):
operator.attrgetter('name'),
None,
get_deps,
noansi=self.noansi,
)
if errors:
raise ProjectError(
@ -508,7 +504,7 @@ class Project(object):
operator.attrgetter('name'),
'Pulling',
limit=5,
noansi=self.noansi)
)
else:
for service in services:
service.pull(ignore_pull_failures, silent=silent)

View File

@ -158,7 +158,6 @@ class Service(object):
secrets=None,
scale=None,
pid_mode=None,
noansi=False,
**options
):
self.name = name
@ -172,7 +171,6 @@ class Service(object):
self.networks = networks or {}
self.secrets = secrets or []
self.scale_num = scale or 1
self.noansi = noansi
self.options = options
def __repr__(self):
@ -395,7 +393,6 @@ class Service(object):
lambda n: create_and_start(self, n),
lambda n: self.get_container_name(n),
"Creating",
noansi=self.noansi,
)
for error in errors.values():
raise OperationFailedError(error)
@ -417,7 +414,6 @@ class Service(object):
recreate,
lambda c: c.name,
"Recreating",
noansi=self.noansi,
)
for error in errors.values():
raise OperationFailedError(error)
@ -438,7 +434,6 @@ class Service(object):
lambda c: self.start_container_if_stopped(c, attach_logs=not detached),
lambda c: c.name,
"Starting",
noansi=self.noansi,
)
for error in errors.values():
@ -460,7 +455,6 @@ class Service(object):
stop_and_remove,
lambda c: c.name,
"Stopping and removing",
noansi=self.noansi,
)
def execute_convergence_plan(self, plan, timeout=None, detached=False,

View File

@ -751,6 +751,14 @@ class CLITestCase(DockerClientTestCase):
for service in services:
assert self.lookup(container, service.name)
@v2_only()
def test_up_no_ansi(self):
self.base_dir = 'tests/fixtures/v2-simple'
result = self.dispatch(['--no-ansi', 'up', '-d'], None)
assert "%c[2K\r" % 27 not in result.stderr
assert "%c[1A" % 27 not in result.stderr
assert "%c[1B" % 27 not in result.stderr
@v2_only()
def test_up_with_default_network_config(self):
filename = 'default-network-config.yml'

View File

@ -8,6 +8,7 @@ from docker.errors import APIError
from compose.parallel import parallel_execute
from compose.parallel import parallel_execute_iter
from compose.parallel import ParallelStreamWriter
from compose.parallel import UpstreamError
@ -62,7 +63,7 @@ def test_parallel_execute_with_limit():
limit=limit,
)
assert results == tasks*[None]
assert results == tasks * [None]
assert errors == {}
@ -133,12 +134,12 @@ def test_parallel_execute_alignment(capsys):
def test_parallel_execute_alignment_noansi(capsys):
ParallelStreamWriter.set_noansi()
results, errors = parallel_execute(
objects=["short", "a very long name"],
func=lambda x: x,
get_name=six.text_type,
msg="Aligning",
noansi=True,
)
assert errors == {}