Переглянути джерело

Removed six

Signed-off-by: Bastian Venthur <[email protected]>
Bastian Venthur 6 роки тому
батько
коміт
5529376d4c

+ 1 - 3
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:

+ 1 - 2
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)

+ 1 - 2
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:

+ 2 - 4
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)

+ 9 - 10
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

+ 1 - 4
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:

+ 7 - 9
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)
 

+ 5 - 6
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,

+ 4 - 5
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)

+ 7 - 8
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):

+ 1 - 2
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

+ 3 - 4
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

+ 9 - 21
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})

+ 4 - 8
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

+ 0 - 2
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

+ 0 - 1
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',
 ]

+ 2 - 9
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')

+ 10 - 11
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'

+ 1 - 2
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(

+ 0 - 10
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']

+ 2 - 2
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
 

+ 1 - 3
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),

+ 6 - 7
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",
     )