Bläddra i källkod

Removed six

Signed-off-by: Bastian Venthur <[email protected]>
Bastian Venthur 6 år sedan
förälder
incheckning
5529376d4c

+ 1 - 3
compose/cli/command.py

@@ -2,8 +2,6 @@ import logging
 import os
 import os
 import re
 import re
 
 
-import six
-
 from . import errors
 from . import errors
 from .. import config
 from .. import config
 from .. import parallel
 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 get_config_path_from_options(base_dir, options, environment):
     def unicode_paths(paths):
     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')
     file_option = options.get('--file')
     if file_option:
     if file_option:

+ 1 - 2
compose/cli/formatter.py

@@ -1,7 +1,6 @@
 import logging
 import logging
 import shutil
 import shutil
 
 
-import six
 import texttable
 import texttable
 
 
 from compose.cli import colors
 from compose.cli import colors
@@ -54,7 +53,7 @@ class ConsoleWarningFormatter(logging.Formatter):
         return ''
         return ''
 
 
     def format(self, record):
     def format(self, record):
-        if isinstance(record.msg, six.binary_type):
+        if isinstance(record.msg, bytes):
             record.msg = record.msg.decode('utf-8')
             record.msg = record.msg.decode('utf-8')
         message = super(ConsoleWarningFormatter, self).format(record)
         message = super(ConsoleWarningFormatter, self).format(record)
         return '{0}{1}'.format(self.get_level_message(record), message)
         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 distro
 import docker
 import docker
-import six
 
 
 import compose
 import compose
 from ..const import IS_WINDOWS_PLATFORM
 from ..const import IS_WINDOWS_PLATFORM
@@ -141,7 +140,7 @@ def human_readable_file_size(size):
 
 
 
 
 def binarystr_to_unicode(s):
 def binarystr_to_unicode(s):
-    if not isinstance(s, six.binary_type):
+    if not isinstance(s, bytes):
         return s
         return s
 
 
     if IS_WINDOWS_PLATFORM:
     if IS_WINDOWS_PLATFORM:

+ 2 - 4
compose/cli/verbose_proxy.py

@@ -3,12 +3,10 @@ import logging
 import pprint
 import pprint
 from itertools import chain
 from itertools import chain
 
 
-import six
-
 
 
 def format_call(args, kwargs):
 def format_call(args, kwargs):
     args = (repr(a) for a in args)
     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)))
     return "({0})".format(", ".join(chain(args, kwargs)))
 
 
 
 
@@ -38,7 +36,7 @@ class VerboseProxy(object):
     def __getattr__(self, name):
     def __getattr__(self, name):
         attr = getattr(self.obj, name)
         attr = getattr(self.obj, name)
 
 
-        if not six.callable(attr):
+        if not callable(attr):
             return attr
             return attr
 
 
         return functools.partial(self.proxy_callable, name)
         return functools.partial(self.proxy_callable, name)

+ 9 - 10
compose/config/config.py

@@ -8,7 +8,6 @@ import sys
 from collections import namedtuple
 from collections import namedtuple
 from operator import attrgetter
 from operator import attrgetter
 
 
-import six
 import yaml
 import yaml
 from cached_property import cached_property
 from cached_property import cached_property
 
 
@@ -201,7 +200,7 @@ class ConfigFile(namedtuple('_ConfigFile', 'filename config')):
                         'Compose file version 1.'.format(self.filename))
                         'Compose file version 1.'.format(self.filename))
             return V1
             return V1
 
 
-        if not isinstance(version, six.string_types):
+        if not isinstance(version, str):
             raise ConfigurationError(
             raise ConfigurationError(
                 'Version in "{}" is invalid - it should be a string.'
                 'Version in "{}" is invalid - it should be a string.'
                 .format(self.filename))
                 .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(env_vars_from_file(env_file, interpolate))
 
 
     env.update(parse_environment(service_dict.get('environment')))
     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):
 def resolve_build_args(buildargs, environment):
     args = parse_build_arguments(buildargs)
     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):
 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):
 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'])
         service_dict['build'] = resolve_build_path(working_dir, service_dict['build'])
     elif isinstance(service_dict['build'], dict):
     elif isinstance(service_dict['build'], dict):
         if 'context' in service_dict['build']:
         if 'context' in service_dict['build']:
@@ -844,7 +843,7 @@ def process_healthcheck(service_dict):
         hc['test'] = ['NONE']
         hc['test'] = ['NONE']
 
 
     for field in ['interval', 'timeout', 'start_period']:
     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
             continue
         hc[field] = parse_nanoseconds_int(hc[field])
         hc[field] = parse_nanoseconds_int(hc[field])
 
 
@@ -1176,7 +1175,7 @@ def merge_ports(md, base, override):
 def merge_build(output, base, override):
 def merge_build(output, base, override):
     def to_dict(service):
     def to_dict(service):
         build_config = service.get('build', {})
         build_config = service.get('build', {})
-        if isinstance(build_config, six.string_types):
+        if isinstance(build_config, str):
             return {'context': build_config}
             return {'context': build_config}
         return build_config
         return build_config
 
 
@@ -1386,7 +1385,7 @@ def normalize_build(service_dict, working_dir, environment):
     if 'build' in service_dict:
     if 'build' in service_dict:
         build = {}
         build = {}
         # Shortcut where specifying a string is treated as the build context
         # 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')
             build['context'] = service_dict.pop('build')
         else:
         else:
             build.update(service_dict['build'])
             build.update(service_dict['build'])
@@ -1412,7 +1411,7 @@ def validate_paths(service_dict):
     if 'build' in service_dict:
     if 'build' in service_dict:
         build = service_dict.get('build', {})
         build = service_dict.get('build', {})
 
 
-        if isinstance(build, six.string_types):
+        if isinstance(build, str):
             build_path = build
             build_path = build
         elif isinstance(build, dict) and 'context' in build:
         elif isinstance(build, dict) and 'context' in build:
             build_path = build['context']
             build_path = build['context']
@@ -1503,7 +1502,7 @@ def merge_list_or_string(base, override):
 def to_list(value):
 def to_list(value):
     if value is None:
     if value is None:
         return []
         return []
-    elif isinstance(value, six.string_types):
+    elif isinstance(value, str):
         return [value]
         return [value]
     else:
     else:
         return value
         return value

+ 1 - 4
compose/config/environment.py

@@ -1,11 +1,8 @@
-import codecs
-import contextlib
 import logging
 import logging
 import os
 import os
 import re
 import re
 
 
 import dotenv
 import dotenv
-import six
 
 
 from ..const import IS_WINDOWS_PLATFORM
 from ..const import IS_WINDOWS_PLATFORM
 from .errors import ConfigurationError
 from .errors import ConfigurationError
@@ -15,7 +12,7 @@ log = logging.getLogger(__name__)
 
 
 
 
 def split_env(env):
 def split_env(env):
-    if isinstance(env, six.binary_type):
+    if isinstance(env, bytes):
         env = env.decode('utf-8', 'replace')
         env = env.decode('utf-8', 'replace')
     key = value = None
     key = value = None
     if '=' in env:
     if '=' in env:

+ 7 - 9
compose/config/interpolation.py

@@ -2,8 +2,6 @@ import logging
 import re
 import re
 from string import Template
 from string import Template
 
 
-import six
-
 from .errors import ConfigurationError
 from .errors import ConfigurationError
 from compose.const import COMPOSEFILE_V2_0 as V2_0
 from compose.const import COMPOSEFILE_V2_0 as V2_0
 from compose.utils import parse_bytes
 from compose.utils import parse_bytes
@@ -74,7 +72,7 @@ def recursive_interpolate(obj, interpolator, config_path):
     def append(config_path, key):
     def append(config_path, key):
         return '{}/{}'.format(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))
         return converter.convert(config_path, interpolator.interpolate(obj))
     if isinstance(obj, dict):
     if isinstance(obj, dict):
         return dict(
         return dict(
@@ -135,7 +133,7 @@ class TemplateWithDefaults(Template):
 
 
             if named is not None:
             if named is not None:
                 val = mapping[named]
                 val = mapping[named]
-                if isinstance(val, six.binary_type):
+                if isinstance(val, bytes):
                     val = val.decode('utf-8')
                     val = val.decode('utf-8')
                 return '%s' % (val,)
                 return '%s' % (val,)
             if mo.group('escaped') is not None:
             if mo.group('escaped') is not None:
@@ -174,7 +172,7 @@ def service_path(*args):
 
 
 
 
 def to_boolean(s):
 def to_boolean(s):
-    if not isinstance(s, six.string_types):
+    if not isinstance(s, str):
         return s
         return s
     s = s.lower()
     s = s.lower()
     if s in ['y', 'yes', 'true', 'on']:
     if s in ['y', 'yes', 'true', 'on']:
@@ -185,11 +183,11 @@ def to_boolean(s):
 
 
 
 
 def to_int(s):
 def to_int(s):
-    if not isinstance(s, six.string_types):
+    if not isinstance(s, str):
         return s
         return s
 
 
     # We must be able to handle octal representation for `mode` values notably
     # 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:]
         s = '0o' + s[1:]
     try:
     try:
         return int(s, base=0)
         return int(s, base=0)
@@ -198,7 +196,7 @@ def to_int(s):
 
 
 
 
 def to_float(s):
 def to_float(s):
-    if not isinstance(s, six.string_types):
+    if not isinstance(s, str):
         return s
         return s
 
 
     try:
     try:
@@ -221,7 +219,7 @@ def bytes_to_int(s):
 
 
 
 
 def to_microseconds(v):
 def to_microseconds(v):
-    if not isinstance(v, six.string_types):
+    if not isinstance(v, str):
         return v
         return v
     return int(parse_nanoseconds_int(v) / 1000)
     return int(parse_nanoseconds_int(v) / 1000)
 
 

+ 5 - 6
compose/config/serialize.py

@@ -1,4 +1,3 @@
-import six
 import yaml
 import yaml
 
 
 from compose.config import types
 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):
 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())
     return representer(data.repr())
 
 
 
 
@@ -22,9 +21,9 @@ def serialize_dict_type(dumper, data):
 
 
 def serialize_string(dumper, data):
 def serialize_string(dumper, data):
     """ Ensure boolean-like strings are quoted in the output """
     """ 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')
         data = data.decode('utf-8')
 
 
     if data.lower() in ('y', 'n', 'yes', 'no', 'on', 'off', 'true', 'false'):
     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):
 def serialize_config(config, image_digests=None, escape_dollar=True):
     if escape_dollar:
     if escape_dollar:
         yaml.SafeDumper.add_representer(str, serialize_string_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:
     else:
         yaml.SafeDumper.add_representer(str, serialize_string)
         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(
     return yaml.safe_dump(
         denormalize_config(config, image_digests),
         denormalize_config(config, image_digests),
         default_flow_style=False,
         default_flow_style=False,

+ 4 - 5
compose/config/types.py

@@ -7,7 +7,6 @@ import os
 import re
 import re
 from collections import namedtuple
 from collections import namedtuple
 
 
-import six
 from docker.utils.ports import build_port_bindings
 from docker.utils.ports import build_port_bindings
 
 
 from ..const import COMPOSEFILE_V1 as V1
 from ..const import COMPOSEFILE_V1 as V1
@@ -101,7 +100,7 @@ def serialize_restart_spec(restart_spec):
         return ''
         return ''
     parts = [restart_spec['Name']]
     parts = [restart_spec['Name']]
     if restart_spec['MaximumRetryCount']:
     if restart_spec['MaximumRetryCount']:
-        parts.append(six.text_type(restart_spec['MaximumRetryCount']))
+        parts.append(str(restart_spec['MaximumRetryCount']))
     return ':'.join(parts)
     return ':'.join(parts)
 
 
 
 
@@ -323,7 +322,7 @@ class ServiceLink(namedtuple('_ServiceLink', 'target alias')):
 class ServiceConfigBase(namedtuple('_ServiceConfigBase', 'source target uid gid mode name')):
 class ServiceConfigBase(namedtuple('_ServiceConfigBase', 'source target uid gid mode name')):
     @classmethod
     @classmethod
     def parse(cls, spec):
     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, None, None, None, None, None)
         return cls(
         return cls(
             spec.get('source'),
             spec.get('source'),
@@ -361,7 +360,7 @@ class ServicePort(namedtuple('_ServicePort', 'target published protocol mode ext
             raise ConfigurationError('Invalid target port: {}'.format(target))
             raise ConfigurationError('Invalid target port: {}'.format(target))
 
 
         if published:
         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)
                 a, b = published.split('-', 1)
                 try:
                 try:
                     int(a)
                     int(a)
@@ -474,7 +473,7 @@ def normalize_port_dict(port):
 class SecurityOpt(namedtuple('_SecurityOpt', 'value src_file')):
 class SecurityOpt(namedtuple('_SecurityOpt', 'value src_file')):
     @classmethod
     @classmethod
     def parse(cls, value):
     def parse(cls, value):
-        if not isinstance(value, six.string_types):
+        if not isinstance(value, str):
             return value
             return value
         # based on https://github.com/docker/cli/blob/9de1b162f/cli/command/container/opts.go#L673-L697
         # based on https://github.com/docker/cli/blob/9de1b162f/cli/command/container/opts.go#L673-L697
         con = value.split('=', 2)
         con = value.split('=', 2)

+ 7 - 8
compose/config/validation.py

@@ -4,7 +4,6 @@ import os
 import re
 import re
 import sys
 import sys
 
 
-import six
 from docker.utils.ports import split_port
 from docker.utils.ports import split_port
 from jsonschema import Draft4Validator
 from jsonschema import Draft4Validator
 from jsonschema import FormatChecker
 from jsonschema import FormatChecker
@@ -72,13 +71,13 @@ def format_ports(instance):
     try:
     try:
         split_port(instance)
         split_port(instance)
     except ValueError as e:
     except ValueError as e:
-        raise ValidationError(six.text_type(e))
+        raise ValidationError(str(e))
     return True
     return True
 
 
 
 
 @FormatChecker.cls_checks(format="expose", raises=ValidationError)
 @FormatChecker.cls_checks(format="expose", raises=ValidationError)
 def format_expose(instance):
 def format_expose(instance):
-    if isinstance(instance, six.string_types):
+    if isinstance(instance, str):
         if not re.match(VALID_EXPOSE_FORMAT, instance):
         if not re.match(VALID_EXPOSE_FORMAT, instance):
             raise ValidationError(
             raise ValidationError(
                 "should be of the format 'PORT[/PROTOCOL]'")
                 "should be of the format 'PORT[/PROTOCOL]'")
@@ -88,7 +87,7 @@ def format_expose(instance):
 
 
 @FormatChecker.cls_checks("subnet_ip_address", raises=ValidationError)
 @FormatChecker.cls_checks("subnet_ip_address", raises=ValidationError)
 def format_subnet_ip_address(instance):
 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 \
         if not re.match(VALID_REGEX_IPV4_CIDR, instance) and \
                 not re.match(VALID_REGEX_IPV6_CIDR, instance):
                 not re.match(VALID_REGEX_IPV6_CIDR, instance):
             raise ValidationError("should use the CIDR format")
             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))))
                 type=anglicize_json_type(python_type_to_yaml_type(config))))
 
 
     for key, value in config.items():
     for key, value in config.items():
-        if not isinstance(key, six.string_types):
+        if not isinstance(key, str):
             raise ConfigurationError(
             raise ConfigurationError(
                 "In file '{filename}', the {section} name {name} must be a "
                 "In file '{filename}', the {section} name {name} must be a "
                 "quoted string, i.e. '{name}'.".format(
                 "quoted string, i.e. '{name}'.".format(
@@ -163,7 +162,7 @@ def validate_top_level_object(config_file):
 
 
 def validate_ulimits(service_config):
 def validate_ulimits(service_config):
     ulimit_config = service_config.config.get('ulimits', {})
     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 isinstance(soft_hard_values, dict):
             if not soft_hard_values['soft'] <= soft_hard_values['hard']:
             if not soft_hard_values['soft'] <= soft_hard_values['hard']:
                 raise ConfigurationError(
                 raise ConfigurationError(
@@ -326,7 +325,7 @@ def handle_generic_error(error, path):
             required_keys)
             required_keys)
 
 
     elif error.cause:
     elif error.cause:
-        error_msg = six.text_type(error.cause)
+        error_msg = str(error.cause)
         msg_format = "{path} is invalid: {msg}"
         msg_format = "{path} is invalid: {msg}"
 
 
     elif error.path:
     elif error.path:
@@ -346,7 +345,7 @@ def parse_key_from_error_msg(error):
 
 
 
 
 def path_string(path):
 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):
 def _parse_valid_types_from_validator(validator):

+ 1 - 2
compose/container.py

@@ -1,6 +1,5 @@
 from functools import reduce
 from functools import reduce
 
 
-import six
 from docker.errors import ImageNotFound
 from docker.errors import ImageNotFound
 
 
 from .const import LABEL_CONTAINER_NUMBER
 from .const import LABEL_CONTAINER_NUMBER
@@ -127,7 +126,7 @@ class Container(object):
 
 
         return ', '.join(
         return ', '.join(
             ','.join(format_port(*item))
             ','.join(format_port(*item))
-            for item in sorted(six.iteritems(self.ports))
+            for item in sorted(self.ports.items())
         )
         )
 
 
     @property
     @property

+ 3 - 4
compose/project.py

@@ -6,7 +6,6 @@ import re
 from functools import reduce
 from functools import reduce
 from os import path
 from os import path
 
 
-import six
 from docker.errors import APIError
 from docker.errors import APIError
 from docker.errors import ImageNotFound
 from docker.errors import ImageNotFound
 from docker.errors import NotFound
 from docker.errors import NotFound
@@ -391,7 +390,7 @@ class Project(object):
             )
             )
             if len(errors):
             if len(errors):
                 combined_errors = '\n'.join([
                 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)
                 raise ProjectError(combined_errors)
 
 
@@ -681,7 +680,7 @@ class Project(object):
                         .format(' '.join(must_build)))
                         .format(' '.join(must_build)))
         if len(errors):
         if len(errors):
             combined_errors = '\n'.join([
             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)
             raise ProjectError(combined_errors)
 
 
@@ -931,7 +930,7 @@ class NeedsPull(Exception):
 
 
 class NoSuchService(Exception):
 class NoSuchService(Exception):
     def __init__(self, name):
     def __init__(self, name):
-        if isinstance(name, six.binary_type):
+        if isinstance(name, bytes):
             name = name.decode('utf-8')
             name = name.decode('utf-8')
         self.name = name
         self.name = name
         self.msg = "No such service: %s" % self.name
         self.msg = "No such service: %s" % self.name

+ 9 - 21
compose/service.py

@@ -4,13 +4,13 @@ import json
 import logging
 import logging
 import os
 import os
 import re
 import re
+import subprocess
 import sys
 import sys
 import tempfile
 import tempfile
 from collections import namedtuple
 from collections import namedtuple
 from collections import OrderedDict
 from collections import OrderedDict
 from operator import attrgetter
 from operator import attrgetter
 
 
-import six
 from docker.errors import APIError
 from docker.errors import APIError
 from docker.errors import ImageNotFound
 from docker.errors import ImageNotFound
 from docker.errors import NotFound
 from docker.errors import NotFound
@@ -59,10 +59,6 @@ from .utils import truncate_id
 from .utils import unique_everseen
 from .utils import unique_everseen
 from compose.cli.utils import binarystr_to_unicode
 from compose.cli.utils import binarystr_to_unicode
 
 
-if six.PY2:
-    import subprocess32 as subprocess
-else:
-    import subprocess
 
 
 log = logging.getLogger(__name__)
 log = logging.getLogger(__name__)
 
 
@@ -422,7 +418,7 @@ class Service(object):
         except NoSuchImageError as e:
         except NoSuchImageError as e:
             log.debug(
             log.debug(
                 'Service %s has diverged: %s',
                 'Service %s has diverged: %s',
-                self.name, six.text_type(e),
+                self.name, str(e),
             )
             )
             return True
             return True
 
 
@@ -972,7 +968,7 @@ class Service(object):
         blkio_config = convert_blkio_config(options.get('blkio_config', None))
         blkio_config = convert_blkio_config(options.get('blkio_config', None))
         log_config = get_log_config(logging_dict)
         log_config = get_log_config(logging_dict)
         init_path = None
         init_path = None
-        if isinstance(options.get('init'), six.string_types):
+        if isinstance(options.get('init'), str):
             init_path = options.get('init')
             init_path = options.get('init')
             options['init'] = True
             options['init'] = True
 
 
@@ -1106,7 +1102,7 @@ class Service(object):
         try:
         try:
             all_events = list(stream_output(build_output, output_stream))
             all_events = list(stream_output(build_output, output_stream))
         except StreamOutputError as e:
         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
         # Ensure the HTTP connection is not reused for another
         # streaming command, as the Docker daemon can sometimes
         # streaming command, as the Docker daemon can sometimes
@@ -1221,7 +1217,7 @@ class Service(object):
             if not ignore_pull_failures:
             if not ignore_pull_failures:
                 raise
                 raise
             else:
             else:
-                log.error(six.text_type(e))
+                log.error(str(e))
 
 
     def pull(self, ignore_pull_failures=False, silent=False, stream=False):
     def pull(self, ignore_pull_failures=False, silent=False, stream=False):
         if 'image' not in self.options:
         if 'image' not in self.options:
@@ -1262,7 +1258,7 @@ class Service(object):
             if not ignore_push_failures:
             if not ignore_push_failures:
                 raise
                 raise
             else:
             else:
-                log.error(six.text_type(e))
+                log.error(str(e))
 
 
     def is_healthy(self):
     def is_healthy(self):
         """ Check that all containers for this service report healthy.
         """ Check that all containers for this service report healthy.
@@ -1628,8 +1624,8 @@ def build_ulimits(ulimit_config):
     if not ulimit_config:
     if not ulimit_config:
         return None
         return None
     ulimits = []
     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})
             ulimits.append({'name': limit_name, 'soft': soft_hard_values, 'hard': soft_hard_values})
         elif isinstance(soft_hard_values, dict):
         elif isinstance(soft_hard_values, dict):
             ulimit_dict = {'name': limit_name}
             ulimit_dict = {'name': limit_name}
@@ -1653,7 +1649,7 @@ def format_environment(environment):
     def format_env(key, value):
     def format_env(key, value):
         if value is None:
         if value is None:
             return key
             return key
-        if isinstance(value, six.binary_type):
+        if isinstance(value, bytes):
             value = value.decode('utf-8')
             value = value.decode('utf-8')
         return '{key}={value}'.format(key=key, value=value)
         return '{key}={value}'.format(key=key, value=value)
 
 
@@ -1704,11 +1700,6 @@ def convert_blkio_config(blkio_config):
 
 
 
 
 def rewrite_build_path(path):
 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):
     if IS_WINDOWS_PLATFORM and not is_url(path) and not path.startswith(WINDOWS_LONGPATH_PREFIX):
         path = WINDOWS_LONGPATH_PREFIX + os.path.normpath(path)
         path = WINDOWS_LONGPATH_PREFIX + os.path.normpath(path)
 
 
@@ -1806,9 +1797,6 @@ class _CLIBuilder(object):
                 line = p.stdout.readline()
                 line = p.stdout.readline()
                 if not line:
                 if not line:
                     break
                     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):
                 if line.startswith(magic_word):
                     appear = True
                     appear = True
                 yield json.dumps({"stream": line})
                 yield json.dumps({"stream": line})

+ 4 - 8
compose/utils.py

@@ -1,11 +1,9 @@
-import codecs
 import hashlib
 import hashlib
 import json.decoder
 import json.decoder
 import logging
 import logging
 import ntpath
 import ntpath
 import random
 import random
 
 
-import six
 from docker.errors import DockerException
 from docker.errors import DockerException
 from docker.utils import parse_bytes as sdk_parse_bytes
 from docker.utils import parse_bytes as sdk_parse_bytes
 
 
@@ -19,9 +17,7 @@ log = logging.getLogger(__name__)
 
 
 
 
 def get_output_stream(stream):
 def get_output_stream(stream):
-    if six.PY3:
-        return stream
-    return codecs.getwriter('utf-8')(stream)
+    return stream
 
 
 
 
 def stream_as_text(stream):
 def stream_as_text(stream):
@@ -32,13 +28,13 @@ def stream_as_text(stream):
     of byte streams.
     of byte streams.
     """
     """
     for data in stream:
     for data in stream:
-        if not isinstance(data, six.text_type):
+        if not isinstance(data, str):
             data = data.decode('utf-8', 'replace')
             data = data.decode('utf-8', 'replace')
         yield data
         yield data
 
 
 
 
 def line_splitter(buffer, separator=u'\n'):
 def line_splitter(buffer, separator=u'\n'):
-    index = buffer.find(six.text_type(separator))
+    index = buffer.find(str(separator))
     if index == -1:
     if index == -1:
         return None
         return None
     return buffer[:index + 1], buffer[index + 1:]
     return buffer[:index + 1], buffer[index + 1:]
@@ -53,7 +49,7 @@ def split_buffer(stream, splitter=None, decoder=lambda a: a):
     of the input.
     of the input.
     """
     """
     splitter = splitter or line_splitter
     splitter = splitter or line_splitter
-    buffered = six.text_type('')
+    buffered = str('')
 
 
     for data in stream_as_text(stream):
     for data in stream_as_text(stream):
         buffered += data
         buffered += data

+ 0 - 2
requirements.txt

@@ -20,8 +20,6 @@ PySocks==1.7.1
 python-dotenv==0.13.0
 python-dotenv==0.13.0
 PyYAML==5.3
 PyYAML==5.3
 requests==2.22.0
 requests==2.22.0
-six==1.12.0
-subprocess32==3.5.4; python_version < '3.2'
 texttable==1.6.2
 texttable==1.6.2
 urllib3==1.25.9; python_version == '3.3'
 urllib3==1.25.9; python_version == '3.3'
 wcwidth==0.1.9
 wcwidth==0.1.9

+ 0 - 1
setup.py

@@ -35,7 +35,6 @@ install_requires = [
     'distro >= 1.5.0, < 2',
     'distro >= 1.5.0, < 2',
     'docker[ssh] >= 3.7.0, < 5',
     'docker[ssh] >= 3.7.0, < 5',
     'dockerpty >= 0.4.1, < 1',
     'dockerpty >= 0.4.1, < 1',
-    'six >= 1.3.0, < 2',
     'jsonschema >= 2.5.1, < 4',
     'jsonschema >= 2.5.1, < 4',
     'python-dotenv >= 0.13.0, < 1',
     '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
 from operator import attrgetter
 
 
 import pytest
 import pytest
-import six
 import yaml
 import yaml
 from docker import errors
 from docker import errors
 
 
@@ -2219,15 +2218,9 @@ services:
     @mock.patch.dict(os.environ)
     @mock.patch.dict(os.environ)
     def test_run_unicode_env_values_from_system(self):
     def test_run_unicode_env_values_from_system(self):
         value = 'ą, ć, ę, ł, ń, ó, ś, ź, ż'
         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'
         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]
         container = self.project.containers(one_off=OneOffFilter.only, stopped=True)[0]
         environment = container.get('Config.Env')
         environment = container.get('Config.Env')

+ 10 - 11
tests/integration/service_test.py

@@ -9,7 +9,6 @@ from os import path
 import pytest
 import pytest
 from docker.errors import APIError
 from docker.errors import APIError
 from docker.errors import ImageNotFound
 from docker.errors import ImageNotFound
-from six import text_type
 
 
 from .. import mock
 from .. import mock
 from ..helpers import BUSYBOX_IMAGE_WITH_TAG
 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:
         with open(os.path.join(base_dir.encode('utf8'), b'foo\xE2bar'), 'w') as f:
             f.write("hello world\n")
             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()
         service.build()
         self.addCleanup(self.client.remove_image, service.image_name)
         self.addCleanup(self.client.remove_image, service.image_name)
         assert self.client.inspect_image('composetest_web')
         assert self.client.inspect_image('composetest_web')
@@ -1063,7 +1062,7 @@ class ServiceTest(DockerClientTestCase):
             f.write("RUN echo ${build_version}\n")
             f.write("RUN echo ${build_version}\n")
 
 
         service = self.create_service('buildwithargs',
         service = self.create_service('buildwithargs',
-                                      build={'context': text_type(base_dir),
+                                      build={'context': str(base_dir),
                                              'args': {"build_version": "1"}})
                                              'args': {"build_version": "1"}})
         service.build()
         service.build()
         self.addCleanup(self.client.remove_image, service.image_name)
         self.addCleanup(self.client.remove_image, service.image_name)
@@ -1080,7 +1079,7 @@ class ServiceTest(DockerClientTestCase):
             f.write("RUN echo ${build_version}\n")
             f.write("RUN echo ${build_version}\n")
 
 
         service = self.create_service('buildwithargs',
         service = self.create_service('buildwithargs',
-                                      build={'context': text_type(base_dir),
+                                      build={'context': str(base_dir),
                                              'args': {"build_version": "1"}})
                                              'args': {"build_version": "1"}})
         service.build(build_args_override={'build_version': '2'})
         service.build(build_args_override={'build_version': '2'})
         self.addCleanup(self.client.remove_image, service.image_name)
         self.addCleanup(self.client.remove_image, service.image_name)
@@ -1096,7 +1095,7 @@ class ServiceTest(DockerClientTestCase):
             f.write('FROM busybox\n')
             f.write('FROM busybox\n')
 
 
         service = self.create_service('buildlabels', build={
         service = self.create_service('buildlabels', build={
-            'context': text_type(base_dir),
+            'context': str(base_dir),
             'labels': {'com.docker.compose.test': 'true'}
             'labels': {'com.docker.compose.test': 'true'}
         })
         })
         service.build()
         service.build()
@@ -1123,7 +1122,7 @@ class ServiceTest(DockerClientTestCase):
         self.client.start(net_container)
         self.client.start(net_container)
 
 
         service = self.create_service('buildwithnet', build={
         service = self.create_service('buildwithnet', build={
-            'context': text_type(base_dir),
+            'context': str(base_dir),
             'network': 'container:{}'.format(net_container['Id'])
             'network': 'container:{}'.format(net_container['Id'])
         })
         })
 
 
@@ -1147,7 +1146,7 @@ class ServiceTest(DockerClientTestCase):
             f.write('LABEL com.docker.compose.test.target=two\n')
             f.write('LABEL com.docker.compose.test.target=two\n')
 
 
         service = self.create_service('buildtarget', build={
         service = self.create_service('buildtarget', build={
-            'context': text_type(base_dir),
+            'context': str(base_dir),
             'target': 'one'
             'target': 'one'
         })
         })
 
 
@@ -1169,7 +1168,7 @@ class ServiceTest(DockerClientTestCase):
             ]))
             ]))
 
 
         service = self.create_service('build_extra_hosts', build={
         service = self.create_service('build_extra_hosts', build={
-            'context': text_type(base_dir),
+            'context': str(base_dir),
             'extra_hosts': {
             'extra_hosts': {
                 'foobar': '127.0.0.1',
                 'foobar': '127.0.0.1',
                 'baz': '127.0.0.1'
                 'baz': '127.0.0.1'
@@ -1191,7 +1190,7 @@ class ServiceTest(DockerClientTestCase):
             f.write('hello world\n')
             f.write('hello world\n')
 
 
         service = self.create_service('build_gzip', build={
         service = self.create_service('build_gzip', build={
-            'context': text_type(base_dir),
+            'context': str(base_dir),
         })
         })
         service.build(gzip=True)
         service.build(gzip=True)
         assert service.image()
         assert service.image()
@@ -1204,7 +1203,7 @@ class ServiceTest(DockerClientTestCase):
             f.write('FROM busybox\n')
             f.write('FROM busybox\n')
 
 
         service = self.create_service('build_isolation', build={
         service = self.create_service('build_isolation', build={
-            'context': text_type(base_dir),
+            'context': str(base_dir),
             'isolation': 'default',
             'isolation': 'default',
         })
         })
         service.build()
         service.build()
@@ -1218,7 +1217,7 @@ class ServiceTest(DockerClientTestCase):
         service = Service(
         service = Service(
             'build_leading_slug', client=self.client,
             'build_leading_slug', client=self.client,
             project='___-composetest', build={
             project='___-composetest', build={
-                'context': text_type(base_dir)
+                'context': str(base_dir)
             }
             }
         )
         )
         assert service.image_name == 'composetest_build_leading_slug'
         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 docker.errors import DockerException
 
 
 from .testcases import DockerClientTestCase
 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):
     def create_volume(self, name, driver=None, opts=None, external=None, custom_name=False):
         if external:
         if external:
             custom_name = True
             custom_name = True
-            if isinstance(external, six.text_type):
+            if isinstance(external, str):
                 name = external
                 name = external
 
 
         vol = Volume(
         vol = Volume(

+ 0 - 10
tests/unit/cli/command_test.py

@@ -2,7 +2,6 @@
 import os
 import os
 
 
 import pytest
 import pytest
-import six
 
 
 from compose.cli.command import get_config_path_from_options
 from compose.cli.command import get_config_path_from_options
 from compose.config.environment import Environment
 from compose.config.environment import Environment
@@ -62,12 +61,3 @@ class TestGetConfigPathFromOptions(object):
         assert get_config_path_from_options(
         assert get_config_path_from_options(
             '.', opts, environment
             '.', opts, environment
         ) == ['就吃饭/docker-compose.yml']
         ) == ['就吃饭/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
 import itertools
+from io import StringIO
 from queue import Queue
 from queue import Queue
 
 
 import pytest
 import pytest
 import requests
 import requests
-import six
 from docker.errors import APIError
 from docker.errors import APIError
 
 
 from compose.cli.log_printer import build_log_generator
 from compose.cli.log_printer import build_log_generator
@@ -19,7 +19,7 @@ from tests import mock
 
 
 @pytest.fixture
 @pytest.fixture
 def output_stream():
 def output_stream():
-    output = six.StringIO()
+    output = StringIO()
     output.flush = mock.Mock()
     output.flush = mock.Mock()
     return output
     return output
 
 

+ 1 - 3
tests/unit/cli/verbose_proxy_test.py

@@ -1,5 +1,3 @@
-import six
-
 from compose.cli import verbose_proxy
 from compose.cli import verbose_proxy
 from tests import unittest
 from tests import unittest
 
 
@@ -7,7 +5,7 @@ from tests import unittest
 class VerboseProxyTestCase(unittest.TestCase):
 class VerboseProxyTestCase(unittest.TestCase):
 
 
     def test_format_call(self):
     def test_format_call(self):
-        prefix = '' if six.PY3 else 'u'
+        prefix = ''
         expected = "(%(p)s'arg1', True, key=%(p)s'value')" % dict(p=prefix)
         expected = "(%(p)s'arg1', True, key=%(p)s'value')" % dict(p=prefix)
         actual = verbose_proxy.format_call(
         actual = verbose_proxy.format_call(
             ("arg1", True),
             ("arg1", True),

+ 6 - 7
tests/unit/parallel_test.py

@@ -1,7 +1,6 @@
 import unittest
 import unittest
 from threading import Lock
 from threading import Lock
 
 
-import six
 from docker.errors import APIError
 from docker.errors import APIError
 
 
 from compose.parallel import GlobalLimit
 from compose.parallel import GlobalLimit
@@ -36,7 +35,7 @@ class ParallelTest(unittest.TestCase):
         results, errors = parallel_execute(
         results, errors = parallel_execute(
             objects=[1, 2, 3, 4, 5],
             objects=[1, 2, 3, 4, 5],
             func=lambda x: x * 2,
             func=lambda x: x * 2,
-            get_name=six.text_type,
+            get_name=str,
             msg="Doubling",
             msg="Doubling",
         )
         )
 
 
@@ -58,7 +57,7 @@ class ParallelTest(unittest.TestCase):
         results, errors = parallel_execute(
         results, errors = parallel_execute(
             objects=list(range(tasks)),
             objects=list(range(tasks)),
             func=f,
             func=f,
-            get_name=six.text_type,
+            get_name=str,
             msg="Testing",
             msg="Testing",
             limit=limit,
             limit=limit,
         )
         )
@@ -82,7 +81,7 @@ class ParallelTest(unittest.TestCase):
         results, errors = parallel_execute(
         results, errors = parallel_execute(
             objects=list(range(tasks)),
             objects=list(range(tasks)),
             func=f,
             func=f,
-            get_name=six.text_type,
+            get_name=str,
             msg="Testing",
             msg="Testing",
         )
         )
 
 
@@ -144,7 +143,7 @@ def test_parallel_execute_alignment(capsys):
     results, errors = parallel_execute(
     results, errors = parallel_execute(
         objects=["short", "a very long name"],
         objects=["short", "a very long name"],
         func=lambda x: x,
         func=lambda x: x,
-        get_name=six.text_type,
+        get_name=str,
         msg="Aligning",
         msg="Aligning",
     )
     )
 
 
@@ -161,7 +160,7 @@ def test_parallel_execute_ansi(capsys):
     results, errors = parallel_execute(
     results, errors = parallel_execute(
         objects=["something", "something more"],
         objects=["something", "something more"],
         func=lambda x: x,
         func=lambda x: x,
-        get_name=six.text_type,
+        get_name=str,
         msg="Control characters",
         msg="Control characters",
     )
     )
 
 
@@ -177,7 +176,7 @@ def test_parallel_execute_noansi(capsys):
     results, errors = parallel_execute(
     results, errors = parallel_execute(
         objects=["something", "something more"],
         objects=["something", "something more"],
         func=lambda x: x,
         func=lambda x: x,
-        get_name=six.text_type,
+        get_name=str,
         msg="Control characters",
         msg="Control characters",
     )
     )