diff --git a/compose/cli/command.py b/compose/cli/command.py index 6c88e5819..f18f76639 100644 --- a/compose/cli/command.py +++ b/compose/cli/command.py @@ -2,8 +2,6 @@ import logging import os import re -import six - from . import errors from .. import config from .. import parallel @@ -107,7 +105,7 @@ def get_config_from_options(base_dir, options, additional_options=None): def get_config_path_from_options(base_dir, options, environment): def unicode_paths(paths): - return [p.decode('utf-8') if isinstance(p, six.binary_type) else p for p in paths] + return [p.decode('utf-8') if isinstance(p, bytes) else p for p in paths] file_option = options.get('--file') if file_option: diff --git a/compose/cli/formatter.py b/compose/cli/formatter.py index 4dabe77c2..a59f0742c 100644 --- a/compose/cli/formatter.py +++ b/compose/cli/formatter.py @@ -1,7 +1,6 @@ import logging import shutil -import six import texttable from compose.cli import colors @@ -54,7 +53,7 @@ class ConsoleWarningFormatter(logging.Formatter): return '' def format(self, record): - if isinstance(record.msg, six.binary_type): + if isinstance(record.msg, bytes): record.msg = record.msg.decode('utf-8') message = super(ConsoleWarningFormatter, self).format(record) return '{0}{1}'.format(self.get_level_message(record), message) diff --git a/compose/cli/utils.py b/compose/cli/utils.py index 65ba74dbb..b91ab6a13 100644 --- a/compose/cli/utils.py +++ b/compose/cli/utils.py @@ -7,7 +7,6 @@ import sys import distro import docker -import six import compose from ..const import IS_WINDOWS_PLATFORM @@ -141,7 +140,7 @@ def human_readable_file_size(size): def binarystr_to_unicode(s): - if not isinstance(s, six.binary_type): + if not isinstance(s, bytes): return s if IS_WINDOWS_PLATFORM: diff --git a/compose/cli/verbose_proxy.py b/compose/cli/verbose_proxy.py index 68dfabe52..1d2f28b5c 100644 --- a/compose/cli/verbose_proxy.py +++ b/compose/cli/verbose_proxy.py @@ -3,12 +3,10 @@ import logging import pprint from itertools import chain -import six - def format_call(args, kwargs): args = (repr(a) for a in args) - kwargs = ("{0!s}={1!r}".format(*item) for item in six.iteritems(kwargs)) + kwargs = ("{0!s}={1!r}".format(*item) for item in kwargs.items()) return "({0})".format(", ".join(chain(args, kwargs))) @@ -38,7 +36,7 @@ class VerboseProxy(object): def __getattr__(self, name): attr = getattr(self.obj, name) - if not six.callable(attr): + if not callable(attr): return attr return functools.partial(self.proxy_callable, name) diff --git a/compose/config/config.py b/compose/config/config.py index 52863b13c..61fad199f 100644 --- a/compose/config/config.py +++ b/compose/config/config.py @@ -8,7 +8,6 @@ import sys from collections import namedtuple from operator import attrgetter -import six import yaml from cached_property import cached_property @@ -201,7 +200,7 @@ class ConfigFile(namedtuple('_ConfigFile', 'filename config')): 'Compose file version 1.'.format(self.filename)) return V1 - if not isinstance(version, six.string_types): + if not isinstance(version, str): raise ConfigurationError( 'Version in "{}" is invalid - it should be a string.' .format(self.filename)) @@ -684,12 +683,12 @@ def resolve_environment(service_dict, environment=None, interpolate=True): env.update(env_vars_from_file(env_file, interpolate)) env.update(parse_environment(service_dict.get('environment'))) - return dict(resolve_env_var(k, v, environment) for k, v in six.iteritems(env)) + return dict(resolve_env_var(k, v, environment) for k, v in env.items()) def resolve_build_args(buildargs, environment): args = parse_build_arguments(buildargs) - return dict(resolve_env_var(k, v, environment) for k, v in six.iteritems(args)) + return dict(resolve_env_var(k, v, environment) for k, v in args.items()) def validate_extended_service_dict(service_dict, filename, service): @@ -776,7 +775,7 @@ def process_service(service_config): def process_build_section(service_dict, working_dir): - if isinstance(service_dict['build'], six.string_types): + if isinstance(service_dict['build'], str): service_dict['build'] = resolve_build_path(working_dir, service_dict['build']) elif isinstance(service_dict['build'], dict): if 'context' in service_dict['build']: @@ -844,7 +843,7 @@ def process_healthcheck(service_dict): hc['test'] = ['NONE'] for field in ['interval', 'timeout', 'start_period']: - if field not in hc or isinstance(hc[field], six.integer_types): + if field not in hc or isinstance(hc[field], int): continue hc[field] = parse_nanoseconds_int(hc[field]) @@ -1176,7 +1175,7 @@ def merge_ports(md, base, override): def merge_build(output, base, override): def to_dict(service): build_config = service.get('build', {}) - if isinstance(build_config, six.string_types): + if isinstance(build_config, str): return {'context': build_config} return build_config @@ -1386,7 +1385,7 @@ def normalize_build(service_dict, working_dir, environment): if 'build' in service_dict: build = {} # Shortcut where specifying a string is treated as the build context - if isinstance(service_dict['build'], six.string_types): + if isinstance(service_dict['build'], str): build['context'] = service_dict.pop('build') else: build.update(service_dict['build']) @@ -1412,7 +1411,7 @@ def validate_paths(service_dict): if 'build' in service_dict: build = service_dict.get('build', {}) - if isinstance(build, six.string_types): + if isinstance(build, str): build_path = build elif isinstance(build, dict) and 'context' in build: build_path = build['context'] @@ -1503,7 +1502,7 @@ def merge_list_or_string(base, override): def to_list(value): if value is None: return [] - elif isinstance(value, six.string_types): + elif isinstance(value, str): return [value] else: return value diff --git a/compose/config/environment.py b/compose/config/environment.py index abcafe0ce..4526d0b3e 100644 --- a/compose/config/environment.py +++ b/compose/config/environment.py @@ -1,11 +1,8 @@ -import codecs -import contextlib import logging import os import re import dotenv -import six from ..const import IS_WINDOWS_PLATFORM from .errors import ConfigurationError @@ -15,7 +12,7 @@ log = logging.getLogger(__name__) def split_env(env): - if isinstance(env, six.binary_type): + if isinstance(env, bytes): env = env.decode('utf-8', 'replace') key = value = None if '=' in env: diff --git a/compose/config/interpolation.py b/compose/config/interpolation.py index f202e9114..9f0fc4847 100644 --- a/compose/config/interpolation.py +++ b/compose/config/interpolation.py @@ -2,8 +2,6 @@ import logging import re from string import Template -import six - from .errors import ConfigurationError from compose.const import COMPOSEFILE_V2_0 as V2_0 from compose.utils import parse_bytes @@ -74,7 +72,7 @@ def recursive_interpolate(obj, interpolator, config_path): def append(config_path, key): return '{}/{}'.format(config_path, key) - if isinstance(obj, six.string_types): + if isinstance(obj, str): return converter.convert(config_path, interpolator.interpolate(obj)) if isinstance(obj, dict): return dict( @@ -135,7 +133,7 @@ class TemplateWithDefaults(Template): if named is not None: val = mapping[named] - if isinstance(val, six.binary_type): + if isinstance(val, bytes): val = val.decode('utf-8') return '%s' % (val,) if mo.group('escaped') is not None: @@ -174,7 +172,7 @@ def service_path(*args): def to_boolean(s): - if not isinstance(s, six.string_types): + if not isinstance(s, str): return s s = s.lower() if s in ['y', 'yes', 'true', 'on']: @@ -185,11 +183,11 @@ def to_boolean(s): def to_int(s): - if not isinstance(s, six.string_types): + if not isinstance(s, str): return s # We must be able to handle octal representation for `mode` values notably - if six.PY3 and re.match('^0[0-9]+$', s.strip()): + if re.match('^0[0-9]+$', s.strip()): s = '0o' + s[1:] try: return int(s, base=0) @@ -198,7 +196,7 @@ def to_int(s): def to_float(s): - if not isinstance(s, six.string_types): + if not isinstance(s, str): return s try: @@ -221,7 +219,7 @@ def bytes_to_int(s): def to_microseconds(v): - if not isinstance(v, six.string_types): + if not isinstance(v, str): return v return int(parse_nanoseconds_int(v) / 1000) diff --git a/compose/config/serialize.py b/compose/config/serialize.py index 79b5777cb..fe0d007a6 100644 --- a/compose/config/serialize.py +++ b/compose/config/serialize.py @@ -1,4 +1,3 @@ -import six import yaml from compose.config import types @@ -12,7 +11,7 @@ from compose.const import COMPOSEFILE_V3_5 as V3_5 def serialize_config_type(dumper, data): - representer = dumper.represent_str if six.PY3 else dumper.represent_unicode + representer = dumper.represent_str return representer(data.repr()) @@ -22,9 +21,9 @@ def serialize_dict_type(dumper, data): def serialize_string(dumper, data): """ Ensure boolean-like strings are quoted in the output """ - representer = dumper.represent_str if six.PY3 else dumper.represent_unicode + representer = dumper.represent_str - if isinstance(data, six.binary_type): + if isinstance(data, bytes): data = data.decode('utf-8') if data.lower() in ('y', 'n', 'yes', 'no', 'on', 'off', 'true', 'false'): @@ -95,10 +94,10 @@ def v3_introduced_name_key(key): def serialize_config(config, image_digests=None, escape_dollar=True): if escape_dollar: yaml.SafeDumper.add_representer(str, serialize_string_escape_dollar) - yaml.SafeDumper.add_representer(six.text_type, serialize_string_escape_dollar) + yaml.SafeDumper.add_representer(str, serialize_string_escape_dollar) else: yaml.SafeDumper.add_representer(str, serialize_string) - yaml.SafeDumper.add_representer(six.text_type, serialize_string) + yaml.SafeDumper.add_representer(str, serialize_string) return yaml.safe_dump( denormalize_config(config, image_digests), default_flow_style=False, diff --git a/compose/config/types.py b/compose/config/types.py index 4a7a25b2b..0c654fa6f 100644 --- a/compose/config/types.py +++ b/compose/config/types.py @@ -7,7 +7,6 @@ import os import re from collections import namedtuple -import six from docker.utils.ports import build_port_bindings from ..const import COMPOSEFILE_V1 as V1 @@ -101,7 +100,7 @@ def serialize_restart_spec(restart_spec): return '' parts = [restart_spec['Name']] if restart_spec['MaximumRetryCount']: - parts.append(six.text_type(restart_spec['MaximumRetryCount'])) + parts.append(str(restart_spec['MaximumRetryCount'])) return ':'.join(parts) @@ -323,7 +322,7 @@ class ServiceLink(namedtuple('_ServiceLink', 'target alias')): class ServiceConfigBase(namedtuple('_ServiceConfigBase', 'source target uid gid mode name')): @classmethod def parse(cls, spec): - if isinstance(spec, six.string_types): + if isinstance(spec, str): return cls(spec, None, None, None, None, None) return cls( spec.get('source'), @@ -361,7 +360,7 @@ class ServicePort(namedtuple('_ServicePort', 'target published protocol mode ext raise ConfigurationError('Invalid target port: {}'.format(target)) if published: - if isinstance(published, six.string_types) and '-' in published: # "x-y:z" format + if isinstance(published, str) and '-' in published: # "x-y:z" format a, b = published.split('-', 1) try: int(a) @@ -474,7 +473,7 @@ def normalize_port_dict(port): class SecurityOpt(namedtuple('_SecurityOpt', 'value src_file')): @classmethod def parse(cls, value): - if not isinstance(value, six.string_types): + if not isinstance(value, str): return value # based on https://github.com/docker/cli/blob/9de1b162f/cli/command/container/opts.go#L673-L697 con = value.split('=', 2) diff --git a/compose/config/validation.py b/compose/config/validation.py index f8513bdef..3161b2395 100644 --- a/compose/config/validation.py +++ b/compose/config/validation.py @@ -4,7 +4,6 @@ import os import re import sys -import six from docker.utils.ports import split_port from jsonschema import Draft4Validator from jsonschema import FormatChecker @@ -72,13 +71,13 @@ def format_ports(instance): try: split_port(instance) except ValueError as e: - raise ValidationError(six.text_type(e)) + raise ValidationError(str(e)) return True @FormatChecker.cls_checks(format="expose", raises=ValidationError) def format_expose(instance): - if isinstance(instance, six.string_types): + if isinstance(instance, str): if not re.match(VALID_EXPOSE_FORMAT, instance): raise ValidationError( "should be of the format 'PORT[/PROTOCOL]'") @@ -88,7 +87,7 @@ def format_expose(instance): @FormatChecker.cls_checks("subnet_ip_address", raises=ValidationError) def format_subnet_ip_address(instance): - if isinstance(instance, six.string_types): + if isinstance(instance, str): if not re.match(VALID_REGEX_IPV4_CIDR, instance) and \ not re.match(VALID_REGEX_IPV6_CIDR, instance): raise ValidationError("should use the CIDR format") @@ -135,7 +134,7 @@ def validate_config_section(filename, config, section): type=anglicize_json_type(python_type_to_yaml_type(config)))) for key, value in config.items(): - if not isinstance(key, six.string_types): + if not isinstance(key, str): raise ConfigurationError( "In file '{filename}', the {section} name {name} must be a " "quoted string, i.e. '{name}'.".format( @@ -163,7 +162,7 @@ def validate_top_level_object(config_file): def validate_ulimits(service_config): ulimit_config = service_config.config.get('ulimits', {}) - for limit_name, soft_hard_values in six.iteritems(ulimit_config): + for limit_name, soft_hard_values in ulimit_config.items(): if isinstance(soft_hard_values, dict): if not soft_hard_values['soft'] <= soft_hard_values['hard']: raise ConfigurationError( @@ -326,7 +325,7 @@ def handle_generic_error(error, path): required_keys) elif error.cause: - error_msg = six.text_type(error.cause) + error_msg = str(error.cause) msg_format = "{path} is invalid: {msg}" elif error.path: @@ -346,7 +345,7 @@ def parse_key_from_error_msg(error): def path_string(path): - return ".".join(c for c in path if isinstance(c, six.string_types)) + return ".".join(c for c in path if isinstance(c, str)) def _parse_valid_types_from_validator(validator): diff --git a/compose/container.py b/compose/container.py index 37de4e6f6..18deabbda 100644 --- a/compose/container.py +++ b/compose/container.py @@ -1,6 +1,5 @@ from functools import reduce -import six from docker.errors import ImageNotFound from .const import LABEL_CONTAINER_NUMBER @@ -127,7 +126,7 @@ class Container(object): return ', '.join( ','.join(format_port(*item)) - for item in sorted(six.iteritems(self.ports)) + for item in sorted(self.ports.items()) ) @property diff --git a/compose/project.py b/compose/project.py index 90a6f5cd5..4c8b197f2 100644 --- a/compose/project.py +++ b/compose/project.py @@ -6,7 +6,6 @@ import re from functools import reduce from os import path -import six from docker.errors import APIError from docker.errors import ImageNotFound from docker.errors import NotFound @@ -391,7 +390,7 @@ class Project(object): ) if len(errors): combined_errors = '\n'.join([ - e.decode('utf-8') if isinstance(e, six.binary_type) else e for e in errors.values() + e.decode('utf-8') if isinstance(e, bytes) else e for e in errors.values() ]) raise ProjectError(combined_errors) @@ -681,7 +680,7 @@ class Project(object): .format(' '.join(must_build))) if len(errors): combined_errors = '\n'.join([ - e.decode('utf-8') if isinstance(e, six.binary_type) else e for e in errors.values() + e.decode('utf-8') if isinstance(e, bytes) else e for e in errors.values() ]) raise ProjectError(combined_errors) @@ -931,7 +930,7 @@ class NeedsPull(Exception): class NoSuchService(Exception): def __init__(self, name): - if isinstance(name, six.binary_type): + if isinstance(name, bytes): name = name.decode('utf-8') self.name = name self.msg = "No such service: %s" % self.name diff --git a/compose/service.py b/compose/service.py index 18173cf70..673b0b335 100644 --- a/compose/service.py +++ b/compose/service.py @@ -4,13 +4,13 @@ import json import logging import os import re +import subprocess import sys import tempfile from collections import namedtuple from collections import OrderedDict from operator import attrgetter -import six from docker.errors import APIError from docker.errors import ImageNotFound from docker.errors import NotFound @@ -59,10 +59,6 @@ from .utils import truncate_id from .utils import unique_everseen from compose.cli.utils import binarystr_to_unicode -if six.PY2: - import subprocess32 as subprocess -else: - import subprocess log = logging.getLogger(__name__) @@ -422,7 +418,7 @@ class Service(object): except NoSuchImageError as e: log.debug( 'Service %s has diverged: %s', - self.name, six.text_type(e), + self.name, str(e), ) return True @@ -972,7 +968,7 @@ class Service(object): blkio_config = convert_blkio_config(options.get('blkio_config', None)) log_config = get_log_config(logging_dict) init_path = None - if isinstance(options.get('init'), six.string_types): + if isinstance(options.get('init'), str): init_path = options.get('init') options['init'] = True @@ -1106,7 +1102,7 @@ class Service(object): try: all_events = list(stream_output(build_output, output_stream)) except StreamOutputError as e: - raise BuildError(self, six.text_type(e)) + raise BuildError(self, str(e)) # Ensure the HTTP connection is not reused for another # streaming command, as the Docker daemon can sometimes @@ -1221,7 +1217,7 @@ class Service(object): if not ignore_pull_failures: raise else: - log.error(six.text_type(e)) + log.error(str(e)) def pull(self, ignore_pull_failures=False, silent=False, stream=False): if 'image' not in self.options: @@ -1262,7 +1258,7 @@ class Service(object): if not ignore_push_failures: raise else: - log.error(six.text_type(e)) + log.error(str(e)) def is_healthy(self): """ Check that all containers for this service report healthy. @@ -1628,8 +1624,8 @@ def build_ulimits(ulimit_config): if not ulimit_config: return None ulimits = [] - for limit_name, soft_hard_values in six.iteritems(ulimit_config): - if isinstance(soft_hard_values, six.integer_types): + for limit_name, soft_hard_values in ulimit_config.items(): + if isinstance(soft_hard_values, int): ulimits.append({'name': limit_name, 'soft': soft_hard_values, 'hard': soft_hard_values}) elif isinstance(soft_hard_values, dict): ulimit_dict = {'name': limit_name} @@ -1653,7 +1649,7 @@ def format_environment(environment): def format_env(key, value): if value is None: return key - if isinstance(value, six.binary_type): + if isinstance(value, bytes): value = value.decode('utf-8') return '{key}={value}'.format(key=key, value=value) @@ -1704,11 +1700,6 @@ def convert_blkio_config(blkio_config): def rewrite_build_path(path): - # python2 os.stat() doesn't support unicode on some UNIX, so we - # encode it to a bytestring to be safe - if not six.PY3 and not IS_WINDOWS_PLATFORM: - path = path.encode('utf8') - if IS_WINDOWS_PLATFORM and not is_url(path) and not path.startswith(WINDOWS_LONGPATH_PREFIX): path = WINDOWS_LONGPATH_PREFIX + os.path.normpath(path) @@ -1806,9 +1797,6 @@ class _CLIBuilder(object): line = p.stdout.readline() if not line: break - # Fix non ascii chars on Python2. To remove when #6890 is complete. - if six.PY2: - magic_word = str(magic_word) if line.startswith(magic_word): appear = True yield json.dumps({"stream": line}) diff --git a/compose/utils.py b/compose/utils.py index 4ea163c42..9170abc13 100644 --- a/compose/utils.py +++ b/compose/utils.py @@ -1,11 +1,9 @@ -import codecs import hashlib import json.decoder import logging import ntpath import random -import six from docker.errors import DockerException from docker.utils import parse_bytes as sdk_parse_bytes @@ -19,9 +17,7 @@ log = logging.getLogger(__name__) def get_output_stream(stream): - if six.PY3: - return stream - return codecs.getwriter('utf-8')(stream) + return stream def stream_as_text(stream): @@ -32,13 +28,13 @@ def stream_as_text(stream): of byte streams. """ for data in stream: - if not isinstance(data, six.text_type): + if not isinstance(data, str): data = data.decode('utf-8', 'replace') yield data def line_splitter(buffer, separator=u'\n'): - index = buffer.find(six.text_type(separator)) + index = buffer.find(str(separator)) if index == -1: return None return buffer[:index + 1], buffer[index + 1:] @@ -53,7 +49,7 @@ def split_buffer(stream, splitter=None, decoder=lambda a: a): of the input. """ splitter = splitter or line_splitter - buffered = six.text_type('') + buffered = str('') for data in stream_as_text(stream): buffered += data diff --git a/requirements.txt b/requirements.txt index 4dea71c14..32257fced 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,8 +20,6 @@ PySocks==1.7.1 python-dotenv==0.13.0 PyYAML==5.3 requests==2.22.0 -six==1.12.0 -subprocess32==3.5.4; python_version < '3.2' texttable==1.6.2 urllib3==1.25.9; python_version == '3.3' wcwidth==0.1.9 diff --git a/setup.py b/setup.py index dad44d72e..e32785225 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,6 @@ install_requires = [ 'distro >= 1.5.0, < 2', 'docker[ssh] >= 3.7.0, < 5', 'dockerpty >= 0.4.1, < 1', - 'six >= 1.3.0, < 2', 'jsonschema >= 2.5.1, < 4', 'python-dotenv >= 0.13.0, < 1', ] diff --git a/tests/acceptance/cli_test.py b/tests/acceptance/cli_test.py index 868e1e227..c84d3f8cb 100644 --- a/tests/acceptance/cli_test.py +++ b/tests/acceptance/cli_test.py @@ -12,7 +12,6 @@ from functools import reduce from operator import attrgetter import pytest -import six import yaml from docker import errors @@ -2219,15 +2218,9 @@ services: @mock.patch.dict(os.environ) def test_run_unicode_env_values_from_system(self): value = 'ą, ć, ę, ł, ń, ó, ś, ź, ż' - if six.PY2: # os.environ doesn't support unicode values in Py2 - os.environ['BAR'] = value.encode('utf-8') - else: # ... and doesn't support byte values in Py3 - os.environ['BAR'] = value + os.environ['BAR'] = value self.base_dir = 'tests/fixtures/unicode-environment' - result = self.dispatch(['run', 'simple']) - - if six.PY2: # Can't retrieve output on Py3. See issue #3670 - assert value in result.stdout.strip() + self.dispatch(['run', 'simple']) container = self.project.containers(one_off=OneOffFilter.only, stopped=True)[0] environment = container.get('Config.Env') diff --git a/tests/integration/service_test.py b/tests/integration/service_test.py index e83b8af07..9af5a2324 100644 --- a/tests/integration/service_test.py +++ b/tests/integration/service_test.py @@ -9,7 +9,6 @@ from os import path import pytest from docker.errors import APIError from docker.errors import ImageNotFound -from six import text_type from .. import mock from ..helpers import BUSYBOX_IMAGE_WITH_TAG @@ -1029,7 +1028,7 @@ class ServiceTest(DockerClientTestCase): with open(os.path.join(base_dir.encode('utf8'), b'foo\xE2bar'), 'w') as f: f.write("hello world\n") - service = self.create_service('web', build={'context': text_type(base_dir)}) + service = self.create_service('web', build={'context': str(base_dir)}) service.build() self.addCleanup(self.client.remove_image, service.image_name) assert self.client.inspect_image('composetest_web') @@ -1063,7 +1062,7 @@ class ServiceTest(DockerClientTestCase): f.write("RUN echo ${build_version}\n") service = self.create_service('buildwithargs', - build={'context': text_type(base_dir), + build={'context': str(base_dir), 'args': {"build_version": "1"}}) service.build() self.addCleanup(self.client.remove_image, service.image_name) @@ -1080,7 +1079,7 @@ class ServiceTest(DockerClientTestCase): f.write("RUN echo ${build_version}\n") service = self.create_service('buildwithargs', - build={'context': text_type(base_dir), + build={'context': str(base_dir), 'args': {"build_version": "1"}}) service.build(build_args_override={'build_version': '2'}) self.addCleanup(self.client.remove_image, service.image_name) @@ -1096,7 +1095,7 @@ class ServiceTest(DockerClientTestCase): f.write('FROM busybox\n') service = self.create_service('buildlabels', build={ - 'context': text_type(base_dir), + 'context': str(base_dir), 'labels': {'com.docker.compose.test': 'true'} }) service.build() @@ -1123,7 +1122,7 @@ class ServiceTest(DockerClientTestCase): self.client.start(net_container) service = self.create_service('buildwithnet', build={ - 'context': text_type(base_dir), + 'context': str(base_dir), 'network': 'container:{}'.format(net_container['Id']) }) @@ -1147,7 +1146,7 @@ class ServiceTest(DockerClientTestCase): f.write('LABEL com.docker.compose.test.target=two\n') service = self.create_service('buildtarget', build={ - 'context': text_type(base_dir), + 'context': str(base_dir), 'target': 'one' }) @@ -1169,7 +1168,7 @@ class ServiceTest(DockerClientTestCase): ])) service = self.create_service('build_extra_hosts', build={ - 'context': text_type(base_dir), + 'context': str(base_dir), 'extra_hosts': { 'foobar': '127.0.0.1', 'baz': '127.0.0.1' @@ -1191,7 +1190,7 @@ class ServiceTest(DockerClientTestCase): f.write('hello world\n') service = self.create_service('build_gzip', build={ - 'context': text_type(base_dir), + 'context': str(base_dir), }) service.build(gzip=True) assert service.image() @@ -1204,7 +1203,7 @@ class ServiceTest(DockerClientTestCase): f.write('FROM busybox\n') service = self.create_service('build_isolation', build={ - 'context': text_type(base_dir), + 'context': str(base_dir), 'isolation': 'default', }) service.build() @@ -1218,7 +1217,7 @@ class ServiceTest(DockerClientTestCase): service = Service( 'build_leading_slug', client=self.client, project='___-composetest', build={ - 'context': text_type(base_dir) + 'context': str(base_dir) } ) assert service.image_name == 'composetest_build_leading_slug' diff --git a/tests/integration/volume_test.py b/tests/integration/volume_test.py index 1e02647fb..2ede7bf28 100644 --- a/tests/integration/volume_test.py +++ b/tests/integration/volume_test.py @@ -1,4 +1,3 @@ -import six from docker.errors import DockerException from .testcases import DockerClientTestCase @@ -24,7 +23,7 @@ class VolumeTest(DockerClientTestCase): def create_volume(self, name, driver=None, opts=None, external=None, custom_name=False): if external: custom_name = True - if isinstance(external, six.text_type): + if isinstance(external, str): name = external vol = Volume( diff --git a/tests/unit/cli/command_test.py b/tests/unit/cli/command_test.py index e2a899517..20702d975 100644 --- a/tests/unit/cli/command_test.py +++ b/tests/unit/cli/command_test.py @@ -2,7 +2,6 @@ import os import pytest -import six from compose.cli.command import get_config_path_from_options from compose.config.environment import Environment @@ -62,12 +61,3 @@ class TestGetConfigPathFromOptions(object): assert get_config_path_from_options( '.', opts, environment ) == ['就吃饭/docker-compose.yml'] - - @pytest.mark.skipif(six.PY3, reason='Env values in Python 3 are already Unicode') - def test_unicode_path_from_env(self): - with mock.patch.dict(os.environ): - os.environ['COMPOSE_FILE'] = b'\xe5\xb0\xb1\xe5\x90\x83\xe9\xa5\xad/docker-compose.yml' - environment = Environment.from_env_file('.') - assert get_config_path_from_options( - '.', {}, environment - ) == ['就吃饭/docker-compose.yml'] diff --git a/tests/unit/cli/log_printer_test.py b/tests/unit/cli/log_printer_test.py index da0abb99f..38dd56c71 100644 --- a/tests/unit/cli/log_printer_test.py +++ b/tests/unit/cli/log_printer_test.py @@ -1,9 +1,9 @@ import itertools +from io import StringIO from queue import Queue import pytest import requests -import six from docker.errors import APIError from compose.cli.log_printer import build_log_generator @@ -19,7 +19,7 @@ from tests import mock @pytest.fixture def output_stream(): - output = six.StringIO() + output = StringIO() output.flush = mock.Mock() return output diff --git a/tests/unit/cli/verbose_proxy_test.py b/tests/unit/cli/verbose_proxy_test.py index 1da1676eb..0da662fd0 100644 --- a/tests/unit/cli/verbose_proxy_test.py +++ b/tests/unit/cli/verbose_proxy_test.py @@ -1,5 +1,3 @@ -import six - from compose.cli import verbose_proxy from tests import unittest @@ -7,7 +5,7 @@ from tests import unittest class VerboseProxyTestCase(unittest.TestCase): def test_format_call(self): - prefix = '' if six.PY3 else 'u' + prefix = '' expected = "(%(p)s'arg1', True, key=%(p)s'value')" % dict(p=prefix) actual = verbose_proxy.format_call( ("arg1", True), diff --git a/tests/unit/parallel_test.py b/tests/unit/parallel_test.py index e4c98b5d6..98412f9a2 100644 --- a/tests/unit/parallel_test.py +++ b/tests/unit/parallel_test.py @@ -1,7 +1,6 @@ import unittest from threading import Lock -import six from docker.errors import APIError from compose.parallel import GlobalLimit @@ -36,7 +35,7 @@ class ParallelTest(unittest.TestCase): results, errors = parallel_execute( objects=[1, 2, 3, 4, 5], func=lambda x: x * 2, - get_name=six.text_type, + get_name=str, msg="Doubling", ) @@ -58,7 +57,7 @@ class ParallelTest(unittest.TestCase): results, errors = parallel_execute( objects=list(range(tasks)), func=f, - get_name=six.text_type, + get_name=str, msg="Testing", limit=limit, ) @@ -82,7 +81,7 @@ class ParallelTest(unittest.TestCase): results, errors = parallel_execute( objects=list(range(tasks)), func=f, - get_name=six.text_type, + get_name=str, msg="Testing", ) @@ -144,7 +143,7 @@ def test_parallel_execute_alignment(capsys): results, errors = parallel_execute( objects=["short", "a very long name"], func=lambda x: x, - get_name=six.text_type, + get_name=str, msg="Aligning", ) @@ -161,7 +160,7 @@ def test_parallel_execute_ansi(capsys): results, errors = parallel_execute( objects=["something", "something more"], func=lambda x: x, - get_name=six.text_type, + get_name=str, msg="Control characters", ) @@ -177,7 +176,7 @@ def test_parallel_execute_noansi(capsys): results, errors = parallel_execute( objects=["something", "something more"], func=lambda x: x, - get_name=six.text_type, + get_name=str, msg="Control characters", )