Merge pull request #7031 from venthur/remove_python2

Removed Python2 support
This commit is contained in:
Ulysses Souza 2020-06-10 17:03:19 +02:00 committed by GitHub
commit 854c14a5bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
83 changed files with 98 additions and 540 deletions

View File

@ -17,9 +17,6 @@
sha: v1.3.4
hooks:
- id: reorder-python-imports
language_version: 'python2.7'
language_version: 'python3.7'
args:
- --add-import
- from __future__ import absolute_import
- --add-import
- from __future__ import unicode_literals
- --py3-plus

View File

@ -24,8 +24,6 @@ RUN apk add --no-cache \
musl-dev \
openssl \
openssl-dev \
python2 \
python2-dev \
zlib-dev
ENV BUILD_BOOTLOADER=1
@ -40,7 +38,6 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
libssl-dev \
make \
openssl \
python2.7-dev \
zlib1g-dev
FROM build-${BUILD_PLATFORM} AS build

View File

@ -1,6 +1,3 @@
#!/usr/bin/env python
from __future__ import absolute_import
from __future__ import unicode_literals
from compose.cli.main import main
main()

View File

@ -1,4 +1,2 @@
from __future__ import absolute_import
from __future__ import unicode_literals
__version__ = '1.27.0dev'

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
from compose.cli.main import main
main()

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
from ..const import IS_WINDOWS_PLATFORM
NAMES = [

View File

@ -1,12 +1,7 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import logging
import os
import re
import six
from . import errors
from .. import config
from .. import parallel
@ -110,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:

View File

@ -1,11 +1,7 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import logging
import os.path
import ssl
import six
from docker import APIClient
from docker import Context
from docker import ContextAPI
@ -47,7 +43,7 @@ def get_client(environment, verbose=False, version=None, context=None):
environment=environment, tls_version=get_tls_version(environment)
)
if verbose:
version_info = six.iteritems(client.version())
version_info = client.version().items()
log.info(get_version_info('full'))
log.info("Docker base_url: %s", client.base_url)
log.info("Docker version: %s",

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
from inspect import getdoc
from docopt import docopt

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import contextlib
import logging
import socket

View File

@ -1,10 +1,6 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import logging
import shutil
import six
import texttable
from compose.cli import colors
@ -57,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)

View File

@ -1,18 +1,14 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import _thread as thread
import sys
from collections import namedtuple
from itertools import cycle
from queue import Empty
from queue import Queue
from threading import Thread
from docker.errors import APIError
from six.moves import _thread as thread
from six.moves.queue import Empty
from six.moves.queue import Queue
from . import colors
from compose import utils
from compose.cli.signals import ShutdownException
from compose.utils import split_buffer
@ -67,7 +63,7 @@ class LogPrinter(object):
self.containers = containers
self.presenters = presenters
self.event_stream = event_stream
self.output = utils.get_output_stream(output)
self.output = output
self.cascade_stop = cascade_stop
self.log_args = log_args or {}

View File

@ -1,7 +1,3 @@
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
import contextlib
import functools
import json

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import signal
from ..const import IS_WINDOWS_PLATFORM

View File

@ -1,7 +1,3 @@
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import math
import os
import platform
@ -11,7 +7,6 @@ import sys
import distro
import docker
import six
import compose
from ..const import IS_WINDOWS_PLATFORM
@ -145,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:

View File

@ -1,17 +1,12 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import functools
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)))
@ -41,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)

View File

@ -1,7 +1,4 @@
# flake8: noqa
from __future__ import absolute_import
from __future__ import unicode_literals
from . import environment
from .config import ConfigurationError
from .config import DOCKER_CONFIG_KEYS

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import functools
import io
import logging
@ -11,7 +8,6 @@ import sys
from collections import namedtuple
from operator import attrgetter
import six
import yaml
from cached_property import cached_property
@ -204,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))
@ -687,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):
@ -779,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']:
@ -847,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])
@ -1179,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
@ -1389,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'])
@ -1415,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']
@ -1506,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

View File

@ -1,12 +1,8 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import logging
import os
import re
import dotenv
import six
from ..const import IS_WINDOWS_PLATFORM
from .errors import ConfigurationError
@ -16,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:

View File

@ -1,5 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
VERSION_EXPLANATION = (

View File

@ -1,12 +1,7 @@
from __future__ import absolute_import
from __future__ import unicode_literals
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
@ -77,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(
@ -138,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:
@ -177,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']:
@ -188,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)
@ -201,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:
@ -224,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)

View File

@ -1,7 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import six
import yaml
from compose.config import types
@ -15,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())
@ -25,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'):
@ -98,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,

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
from compose.config.errors import DependencyError

View File

@ -1,16 +1,12 @@
"""
Types for objects parsed from the configuration.
"""
from __future__ import absolute_import
from __future__ import unicode_literals
import json
import ntpath
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
@ -104,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)
@ -326,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'),
@ -364,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)
@ -477,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)

View File

@ -1,13 +1,9 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import json
import logging
import os
import re
import sys
import six
from docker.utils.ports import split_port
from jsonschema import Draft4Validator
from jsonschema import FormatChecker
@ -75,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]'")
@ -91,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")
@ -138,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(
@ -166,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(
@ -329,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:
@ -349,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):

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import sys
from .version import ComposeVersion

View File

@ -1,9 +1,5 @@
from __future__ import absolute_import
from __future__ import unicode_literals
from functools import reduce
import six
from docker.errors import ImageNotFound
from .const import LABEL_CONTAINER_NUMBER
@ -130,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

View File

@ -1,5 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
class OperationFailedError(Exception):

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import logging
import re
from collections import OrderedDict

View File

@ -1,18 +1,15 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import _thread as thread
import logging
import operator
import sys
from queue import Empty
from queue import Queue
from threading import Lock
from threading import Semaphore
from threading import Thread
from docker.errors import APIError
from docker.errors import ImageNotFound
from six.moves import _thread as thread
from six.moves.queue import Empty
from six.moves.queue import Queue
from compose.cli.colors import green
from compose.cli.colors import red
@ -21,7 +18,6 @@ from compose.const import PARALLEL_LIMIT
from compose.errors import HealthCheckFailed
from compose.errors import NoHealthCheckConfigured
from compose.errors import OperationFailedError
from compose.utils import get_output_stream
log = logging.getLogger(__name__)
@ -85,7 +81,7 @@ def parallel_execute(objects, func, get_name, msg, get_deps=None, limit=None, fa
in the CLI logs, but don't raise an exception (such as attempting to start 0 containers)
"""
objects = list(objects)
stream = get_output_stream(sys.stderr)
stream = sys.stderr
if ParallelStreamWriter.instance:
writer = ParallelStreamWriter.instance

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
from compose import utils
@ -18,7 +15,7 @@ def write_to_stream(s, stream):
def stream_output(output, stream):
is_terminal = hasattr(stream, 'isatty') and stream.isatty()
stream = utils.get_output_stream(stream)
stream = stream
lines = {}
diff = 0

View File

@ -1,15 +1,11 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import datetime
import enum
import logging
import operator
import re
from functools import reduce
from os import path
import enum
import six
from docker.errors import APIError
from docker.errors import ImageNotFound
from docker.errors import NotFound
@ -394,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)
@ -684,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)
@ -934,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

View File

@ -1,19 +1,16 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import enum
import itertools
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 enum
import six
from docker.errors import APIError
from docker.errors import ImageNotFound
from docker.errors import NotFound
@ -62,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__)
@ -425,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
@ -975,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
@ -1109,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
@ -1224,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:
@ -1265,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.
@ -1631,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}
@ -1656,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)
@ -1707,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)
@ -1809,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})

View File

@ -31,9 +31,6 @@ https://golang.org/pkg/time/#ParseDuration
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from __future__ import absolute_import
from __future__ import unicode_literals
import re
HOURS = r'(?P<hours>[\d.]+)h'

View File

@ -1,14 +1,9 @@
from __future__ import absolute_import
from __future__ import unicode_literals
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
@ -21,12 +16,6 @@ json_decoder = json.JSONDecoder()
log = logging.getLogger(__name__)
def get_output_stream(stream):
if six.PY3:
return stream
return codecs.getwriter('utf-8')(stream)
def stream_as_text(stream):
"""Given a stream of bytes or text, if any of the items in the stream
are bytes convert them to text.
@ -35,13 +24,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:]
@ -56,7 +45,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

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
from distutils.version import LooseVersion

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import logging
import re

View File

@ -3,9 +3,6 @@
Migrate a Compose file from the V1 format in Compose 1.5 to the V2 format
supported by Compose 1.6+
"""
from __future__ import absolute_import
from __future__ import unicode_literals
import argparse
import logging
import sys

View File

@ -1,5 +1,4 @@
backports.shutil_get_terminal_size==1.0.0
backports.ssl-match-hostname==3.5.0.1; python_version < '3'
cached-property==1.5.1
certifi==2020.4.5.1
chardet==3.0.4
@ -21,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'
websocket-client==0.57.0

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import os

View File

@ -1,126 +0,0 @@
#!/usr/bin/env python3
from __future__ import absolute_import
from __future__ import unicode_literals
import re
import click
from git import Repo
from utils import update_init_py_version
from utils import update_run_sh_version
from utils import yesno
VALID_VERSION_PATTERN = re.compile(r"^\d+\.\d+\.\d+(-rc\d+)?$")
class Version(str):
def matching_groups(self):
match = VALID_VERSION_PATTERN.match(self)
if not match:
return False
return match.groups()
def is_ga_version(self):
groups = self.matching_groups()
if not groups:
return False
rc_suffix = groups[1]
return not rc_suffix
def validate(self):
return len(self.matching_groups()) > 0
def branch_name(self):
if not self.validate():
return None
rc_part = self.matching_groups()[0]
ver = self
if rc_part:
ver = ver[:-len(rc_part)]
tokens = ver.split(".")
tokens[-1] = 'x'
return ".".join(tokens)
def create_bump_commit(repository, version):
print('Creating bump commit...')
repository.commit('-a', '-s', '-m "Bump {}"'.format(version), '--no-verify')
def validate_environment(version, repository):
if not version.validate():
print('Version "{}" has an invalid format. This should follow D+.D+.D+(-rcD+). '
'Like: 1.26.0 or 1.26.0-rc1'.format(version))
return False
expected_branch = version.branch_name()
if str(repository.active_branch) != expected_branch:
print('Cannot tag in this branch with version "{}". '
'Please checkout "{}" to tag'.format(version, version.branch_name()))
return False
return True
@click.group()
def cli():
pass
@cli.command()
@click.argument('version')
def tag(version):
"""
Updates the version related files and tag
"""
repo = Repo(".")
version = Version(version)
if not validate_environment(version, repo):
return
update_init_py_version(version)
update_run_sh_version(version)
input('Please add the release notes to the CHANGELOG.md file, then press Enter to continue.')
proceed = False
while not proceed:
print(repo.git.diff())
proceed = yesno('Are these changes ok? y/N ', default=False)
if repo.git.diff():
create_bump_commit(repo.git, version)
else:
print('No changes to commit. Exiting...')
return
repo.create_tag(version)
print('Please, check the changes. If everything is OK, you just need to push with:\n'
'$ git push --tags upstream {}'.format(version.branch_name()))
@cli.command()
@click.argument('version')
def push_latest(version):
"""
TODO Pushes the latest tag pointing to a certain GA version
"""
raise NotImplementedError
@cli.command()
@click.argument('version')
def ghtemplate(version):
"""
TODO Generates the github release page content
"""
version = Version(version)
raise NotImplementedError
if __name__ == '__main__':
cli()

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import os
import re

View File

@ -11,7 +11,7 @@ docker run --rm \
"$TAG" tox -e pre-commit
get_versions="docker run --rm
--entrypoint=/code/.tox/py27/bin/python
--entrypoint=/code/.tox/py37/bin/python
$TAG
/code/script/test/versions.py docker/docker-ce,moby/moby"
@ -23,7 +23,7 @@ fi
BUILD_NUMBER=${BUILD_NUMBER-$USER}
PY_TEST_VERSIONS=${PY_TEST_VERSIONS:-py27,py37}
PY_TEST_VERSIONS=${PY_TEST_VERSIONS:-py37}
for version in $DOCKER_VERSIONS; do
>&2 echo "Running tests against Docker $version"

View File

@ -21,10 +21,6 @@ For example, if the list of versions is:
`default` would return `1.7.1` and
`recent -n 3` would return `1.8.0-rc2 1.7.1 1.6.2`
"""
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
import argparse
import itertools
import operator

View File

@ -1,9 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
import codecs
import os
import re
@ -39,7 +35,6 @@ install_requires = [
'distro >= 1.5.0, < 2',
'docker[ssh] >= 4.2.1, < 5',
'dockerpty >= 0.4.1, < 1',
'six >= 1.3.0, < 2',
'jsonschema >= 2.5.1, < 4',
'python-dotenv >= 0.13.0, < 1',
]
@ -108,8 +103,6 @@ setup(
'Environment :: Console',
'Intended Audience :: Developers',
'License :: OSI Approved :: Apache Software License',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.6',

View File

@ -1,14 +1,2 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import sys
if sys.version_info >= (2, 7):
import unittest # NOQA
else:
import unittest2 as unittest # NOQA
try:
from unittest import mock
except ImportError:
import mock # NOQA
from unittest import mock # NOQA

View File

@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals
import datetime
import json
import os.path
@ -15,7 +12,6 @@ from functools import reduce
from operator import attrgetter
import pytest
import six
import yaml
from docker import errors
@ -2222,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
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')

View File

@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals
import os
import shutil
import unittest

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import pytest
import tests.acceptance.cli_test

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import contextlib
import os

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import tempfile
from ddt import data

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import pytest
from .testcases import DockerClientTestCase

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import copy
import json
import os

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import pytest
from .. import mock

View File

@ -1,18 +1,14 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import os
import re
import shutil
import tempfile
from distutils.spawn import find_executable
from io import StringIO
from os import path
import pytest
from docker.errors import APIError
from docker.errors import ImageNotFound
from six import StringIO
from six import text_type
from .. import mock
from ..helpers import BUSYBOX_IMAGE_WITH_TAG
@ -1035,7 +1031,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')
@ -1069,7 +1065,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)
@ -1086,7 +1082,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)
@ -1102,7 +1098,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()
@ -1129,7 +1125,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'])
})
@ -1153,7 +1149,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'
})
@ -1175,7 +1171,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'
@ -1197,7 +1193,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()
@ -1210,7 +1206,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()
@ -1224,7 +1220,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'

View File

@ -2,9 +2,6 @@
Integration tests which cover state convergence (aka smart recreate) performed
by `docker-compose up`.
"""
from __future__ import absolute_import
from __future__ import unicode_literals
import copy
import os
import shutil

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import functools
import os

View File

@ -1,7 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import six
from docker.errors import DockerException
from .testcases import DockerClientTestCase
@ -27,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(

View File

@ -1,11 +1,7 @@
# ~*~ encoding: utf-8 ~*~
from __future__ import absolute_import
from __future__ import unicode_literals
import os
import pytest
import six
from compose.cli.command import get_config_path_from_options
from compose.config.environment import Environment
@ -65,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']

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import os
import platform
import ssl

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import pytest
from docker.errors import APIError
from requests.exceptions import ConnectionError

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import logging
from compose.cli import colors

View File

@ -1,13 +1,10 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import itertools
from io import StringIO
from queue import Queue
import pytest
import requests
import six
from docker.errors import APIError
from six.moves.queue import Queue
from compose.cli.log_printer import build_log_generator
from compose.cli.log_printer import build_log_presenters
@ -22,7 +19,7 @@ from tests import mock
@pytest.fixture
def output_stream():
output = six.StringIO()
output = StringIO()
output.flush = mock.Mock()
return output

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import logging
import docker

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import unittest
from compose.cli.utils import human_readable_file_size

View File

@ -1,8 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import six
from compose.cli import verbose_proxy
from tests import unittest
@ -10,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),

View File

@ -1,7 +1,4 @@
# encoding: utf-8
from __future__ import absolute_import
from __future__ import unicode_literals
import os
import shutil
import tempfile

View File

@ -1,8 +1,4 @@
# encoding: utf-8
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
import codecs
import os
import shutil

View File

@ -1,8 +1,4 @@
# encoding: utf-8
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
import codecs
import os
import shutil

View File

@ -1,7 +1,4 @@
# encoding: utf-8
from __future__ import absolute_import
from __future__ import unicode_literals
import pytest
from compose.config.environment import Environment

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import pytest
from compose.config.errors import DependencyError

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import pytest
from compose.config.errors import ConfigurationError

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import docker
from .. import mock

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import pytest
from .. import mock

View File

@ -1,10 +1,6 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import unittest
from threading import Lock
import six
from docker.errors import APIError
from compose.parallel import GlobalLimit
@ -39,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",
)
@ -61,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,
)
@ -85,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",
)
@ -147,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",
)
@ -164,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",
)
@ -180,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",
)

View File

@ -1,14 +1,10 @@
# ~*~ encoding: utf-8 ~*~
from __future__ import absolute_import
from __future__ import unicode_literals
import io
import os
import random
import shutil
import tempfile
from six import StringIO
from io import StringIO
from compose import progress_stream
from tests import unittest

View File

@ -1,7 +1,4 @@
# encoding: utf-8
from __future__ import absolute_import
from __future__ import unicode_literals
import datetime
import os
import tempfile

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import docker
import pytest
from docker.constants import DEFAULT_DOCKER_API_VERSION

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
from .. import unittest
from compose.utils import split_buffer

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
from compose import timeparse

View File

@ -1,7 +1,4 @@
# encoding: utf-8
from __future__ import absolute_import
from __future__ import unicode_literals
from compose import utils

View File

@ -1,6 +1,3 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import docker
import pytest

View File

@ -1,5 +1,5 @@
[tox]
envlist = py27,py37,pre-commit
envlist = py37,pre-commit
[testenv]
usedevelop=True