Bläddra i källkod

Make 'version' a string

Signed-off-by: Aanand Prasad <[email protected]>
Aanand Prasad 9 år sedan
förälder
incheckning
aeef61fcd8

+ 20 - 13
compose/config/config.py

@@ -14,6 +14,8 @@ import six
 import yaml
 from cached_property import cached_property
 
+from ..const import COMPOSEFILE_V1 as V1
+from ..const import COMPOSEFILE_V2_0 as V2_0
 from ..const import COMPOSEFILE_VERSIONS
 from .errors import CircularReference
 from .errors import ComposeFileNotFound
@@ -129,25 +131,34 @@ class ConfigFile(namedtuple('_ConfigFile', 'filename config')):
 
     @cached_property
     def version(self):
-        version = self.config.get('version', 1)
+        version = self.config.get('version', V1)
+
         if isinstance(version, dict):
             log.warn("Unexpected type for field 'version', in file {} assuming "
                      "version is the name of a service, and defaulting to "
                      "Compose file version 1".format(self.filename))
-            return 1
+            return V1
+
+        if version == '2':
+            version = V2_0
+
+        if version not in COMPOSEFILE_VERSIONS:
+            raise ConfigurationError(
+                'Invalid Compose file version: {0}'.format(version))
+
         return version
 
     def get_service(self, name):
         return self.get_service_dicts()[name]
 
     def get_service_dicts(self):
-        return self.config if self.version == 1 else self.config.get('services', {})
+        return self.config if self.version == V1 else self.config.get('services', {})
 
     def get_volumes(self):
-        return {} if self.version == 1 else self.config.get('volumes', {})
+        return {} if self.version == V1 else self.config.get('volumes', {})
 
     def get_networks(self):
-        return {} if self.version == 1 else self.config.get('networks', {})
+        return {} if self.version == V1 else self.config.get('networks', {})
 
 
 class Config(namedtuple('_Config', 'version services volumes networks')):
@@ -209,10 +220,6 @@ def validate_config_version(config_files):
                     next_file.filename,
                     next_file.version))
 
-    if main_file.version not in COMPOSEFILE_VERSIONS:
-        raise ConfigurationError(
-            'Invalid Compose file version: {0}'.format(main_file.version))
-
 
 def get_default_config_files(base_dir):
     (candidates, path) = find_candidates_in_parent_dirs(SUPPORTED_FILENAMES, base_dir)
@@ -276,7 +283,7 @@ def load(config_details):
         main_file,
         [file.get_service_dicts() for file in config_details.config_files])
 
-    if main_file.version >= 2:
+    if main_file.version != V1:
         for service_dict in service_dicts:
             match_named_volumes(service_dict, volumes)
 
@@ -361,7 +368,7 @@ def process_config_file(config_file, service_name=None):
 
     interpolated_config = interpolate_environment_variables(service_dicts, 'service')
 
-    if config_file.version == 2:
+    if config_file.version == V2_0:
         processed_config = dict(config_file.config)
         processed_config['services'] = services = interpolated_config
         processed_config['volumes'] = interpolate_environment_variables(
@@ -369,7 +376,7 @@ def process_config_file(config_file, service_name=None):
         processed_config['networks'] = interpolate_environment_variables(
             config_file.get_networks(), 'network')
 
-    if config_file.version == 1:
+    if config_file.version == V1:
         processed_config = services = interpolated_config
 
     config_file = config_file._replace(config=processed_config)
@@ -653,7 +660,7 @@ def merge_service_dicts(base, override, version):
         if field in base or field in override:
             d[field] = override.get(field, base.get(field))
 
-    if version == 1:
+    if version == V1:
         legacy_v1_merge_image_or_build(d, base, override)
     else:
         merge_build(d, base, override)

+ 3 - 3
compose/config/fields_schema_v2.json → compose/config/fields_schema_v2.0.json

@@ -1,18 +1,18 @@
 {
   "$schema": "http://json-schema.org/draft-04/schema#",
   "type": "object",
-  "id": "fields_schema_v2.json",
+  "id": "fields_schema_v2.0.json",
 
   "properties": {
     "version": {
-      "enum": [2]
+      "type": "string"
     },
     "services": {
       "id": "#/properties/services",
       "type": "object",
       "patternProperties": {
         "^[a-zA-Z0-9._-]+$": {
-          "$ref": "service_schema_v2.json#/definitions/service"
+          "$ref": "service_schema_v2.0.json#/definitions/service"
         }
       },
       "additionalProperties": false

+ 1 - 1
compose/config/service_schema_v2.json → compose/config/service_schema_v2.0.json

@@ -1,6 +1,6 @@
 {
   "$schema": "http://json-schema.org/draft-04/schema#",
-  "id": "service_schema_v2.json",
+  "id": "service_schema_v2.0.json",
 
   "type": "object",
 

+ 2 - 1
compose/config/types.py

@@ -7,6 +7,7 @@ from __future__ import unicode_literals
 import os
 from collections import namedtuple
 
+from compose.config.config import V1
 from compose.config.errors import ConfigurationError
 from compose.const import IS_WINDOWS_PLATFORM
 
@@ -16,7 +17,7 @@ class VolumeFromSpec(namedtuple('_VolumeFromSpec', 'source mode type')):
     # TODO: drop service_names arg when v1 is removed
     @classmethod
     def parse(cls, volume_from_config, service_names, version):
-        func = cls.parse_v1 if version == 1 else cls.parse_v2
+        func = cls.parse_v1 if version == V1 else cls.parse_v2
         return func(service_names, volume_from_config)
 
     @classmethod

+ 6 - 3
compose/const.py

@@ -14,9 +14,12 @@ LABEL_PROJECT = 'com.docker.compose.project'
 LABEL_SERVICE = 'com.docker.compose.service'
 LABEL_VERSION = 'com.docker.compose.version'
 LABEL_CONFIG_HASH = 'com.docker.compose.config-hash'
-COMPOSEFILE_VERSIONS = (1, 2)
+
+COMPOSEFILE_V1 = '1'
+COMPOSEFILE_V2_0 = '2.0'
+COMPOSEFILE_VERSIONS = (COMPOSEFILE_V1, COMPOSEFILE_V2_0)
 
 API_VERSIONS = {
-    1: '1.21',
-    2: '1.22',
+    COMPOSEFILE_V1: '1.21',
+    COMPOSEFILE_V2_0: '1.22',
 }

+ 3 - 2
compose/project.py

@@ -10,6 +10,7 @@ from docker.errors import NotFound
 
 from . import parallel
 from .config import ConfigurationError
+from .config.config import V1
 from .config.sort_services import get_container_name_from_network_mode
 from .config.sort_services import get_service_name_from_network_mode
 from .const import DEFAULT_TIMEOUT
@@ -56,7 +57,7 @@ class Project(object):
         """
         Construct a Project from a config.Config object.
         """
-        use_networking = (config_data.version and config_data.version >= 2)
+        use_networking = (config_data.version and config_data.version != V1)
         project = cls(name, [], client, use_networking=use_networking)
 
         network_config = config_data.networks or {}
@@ -94,7 +95,7 @@ class Project(object):
             network_mode = project.get_network_mode(service_dict, networks)
             volumes_from = get_volumes_from(project, service_dict)
 
-            if config_data.version == 2:
+            if config_data.version != V1:
                 service_volumes = service_dict.get('volumes', [])
                 for volume_spec in service_volumes:
                     if volume_spec.is_named_volume:

+ 4 - 4
docker-compose.spec

@@ -23,8 +23,8 @@ exe = EXE(pyz,
                 'DATA'
             ),
             (
-                'compose/config/fields_schema_v2.json',
-                'compose/config/fields_schema_v2.json',
+                'compose/config/fields_schema_v2.0.json',
+                'compose/config/fields_schema_v2.0.json',
                 'DATA'
             ),
             (
@@ -33,8 +33,8 @@ exe = EXE(pyz,
                 'DATA'
             ),
             (
-                'compose/config/service_schema_v2.json',
-                'compose/config/service_schema_v2.json',
+                'compose/config/service_schema_v2.0.json',
+                'compose/config/service_schema_v2.0.json',
                 'DATA'
             ),
             (

+ 1 - 1
tests/acceptance/cli_test.py

@@ -177,7 +177,7 @@ class CLITestCase(DockerClientTestCase):
 
         output = yaml.load(result.stdout)
         expected = {
-            'version': 2,
+            'version': '2.0',
             'volumes': {'data': {'driver': 'local'}},
             'networks': {'front': {}},
             'services': {

+ 1 - 1
tests/fixtures/extends/invalid-net-v2.yml

@@ -1,4 +1,4 @@
-version: 2
+version: "2"
 services:
   myweb:
     build: '.'

+ 1 - 1
tests/fixtures/logging-composefile/docker-compose.yml

@@ -1,4 +1,4 @@
-version: 2
+version: "2"
 services:
   simple:
     image: busybox:latest

+ 1 - 1
tests/fixtures/net-container/v2-invalid.yml

@@ -1,4 +1,4 @@
-version: 2
+version: "2"
 
 services:
   foo:

+ 1 - 1
tests/fixtures/networks/bridge.yml

@@ -1,4 +1,4 @@
-version: 2
+version: "2"
 
 services:
   web:

+ 1 - 1
tests/fixtures/networks/default-network-config.yml

@@ -1,4 +1,4 @@
-version: 2
+version: "2"
 services:
   simple:
     image: busybox:latest

+ 1 - 1
tests/fixtures/networks/docker-compose.yml

@@ -1,4 +1,4 @@
-version: 2
+version: "2"
 
 services:
   web:

+ 1 - 1
tests/fixtures/networks/external-default.yml

@@ -1,4 +1,4 @@
-version: 2
+version: "2"
 services:
   simple:
     image: busybox:latest

+ 1 - 1
tests/fixtures/networks/external-networks.yml

@@ -1,4 +1,4 @@
-version: 2
+version: "2"
 
 services:
   web:

+ 1 - 1
tests/fixtures/networks/missing-network.yml

@@ -1,4 +1,4 @@
-version: 2
+version: "2"
 
 services:
   web:

+ 1 - 1
tests/fixtures/networks/network-mode.yml

@@ -1,4 +1,4 @@
-version: 2
+version: "2"
 
 services:
   bridge:

+ 1 - 1
tests/fixtures/no-services/docker-compose.yml

@@ -1,4 +1,4 @@
-version: 2
+version: "2"
 
 networks:
   foo: {}

+ 1 - 1
tests/fixtures/sleeps-composefile/docker-compose.yml

@@ -1,5 +1,5 @@
 
-version: 2
+version: "2"
 
 services:
   simple:

+ 1 - 1
tests/fixtures/v2-full/docker-compose.yml

@@ -1,5 +1,5 @@
 
-version: 2
+version: "2"
 
 volumes:
   data:

+ 1 - 1
tests/fixtures/v2-simple/docker-compose.yml

@@ -1,4 +1,4 @@
-version: 2
+version: "2"
 services:
   simple:
     image: busybox:latest

+ 1 - 1
tests/fixtures/v2-simple/links-invalid.yml

@@ -1,4 +1,4 @@
-version: 2
+version: "2"
 services:
   simple:
     image: busybox:latest

+ 15 - 14
tests/integration/project_test.py

@@ -10,6 +10,7 @@ from docker.errors import NotFound
 from .testcases import DockerClientTestCase
 from compose.config import config
 from compose.config import ConfigurationError
+from compose.config.config import V2_0
 from compose.config.types import VolumeFromSpec
 from compose.config.types import VolumeSpec
 from compose.const import LABEL_PROJECT
@@ -112,7 +113,7 @@ class ProjectTest(DockerClientTestCase):
             name='composetest',
             client=self.client,
             config_data=build_service_dicts({
-                'version': 2,
+                'version': V2_0,
                 'services': {
                     'net': {
                         'image': 'busybox:latest',
@@ -139,7 +140,7 @@ class ProjectTest(DockerClientTestCase):
             return Project.from_config(
                 name='composetest',
                 config_data=build_service_dicts({
-                    'version': 2,
+                    'version': V2_0,
                     'services': {
                         'web': {
                             'image': 'busybox:latest',
@@ -559,7 +560,7 @@ class ProjectTest(DockerClientTestCase):
     @v2_only()
     def test_project_up_networks(self):
         config_data = config.Config(
-            version=2,
+            version=V2_0,
             services=[{
                 'name': 'web',
                 'image': 'busybox:latest',
@@ -592,7 +593,7 @@ class ProjectTest(DockerClientTestCase):
     @v2_only()
     def test_up_with_ipam_config(self):
         config_data = config.Config(
-            version=2,
+            version=V2_0,
             services=[],
             volumes={},
             networks={
@@ -651,7 +652,7 @@ class ProjectTest(DockerClientTestCase):
         vol_name = '{0:x}'.format(random.getrandbits(32))
         full_vol_name = 'composetest_{0}'.format(vol_name)
         config_data = config.Config(
-            version=2,
+            version=V2_0,
             services=[{
                 'name': 'web',
                 'image': 'busybox:latest',
@@ -677,7 +678,7 @@ class ProjectTest(DockerClientTestCase):
         base_file = config.ConfigFile(
             'base.yml',
             {
-                'version': 2,
+                'version': V2_0,
                 'services': {
                     'simple': {'image': 'busybox:latest', 'command': 'top'},
                     'another': {
@@ -696,7 +697,7 @@ class ProjectTest(DockerClientTestCase):
         override_file = config.ConfigFile(
             'override.yml',
             {
-                'version': 2,
+                'version': V2_0,
                 'services': {
                     'another': {
                         'logging': {
@@ -729,7 +730,7 @@ class ProjectTest(DockerClientTestCase):
         vol_name = '{0:x}'.format(random.getrandbits(32))
         full_vol_name = 'composetest_{0}'.format(vol_name)
         config_data = config.Config(
-            version=2,
+            version=V2_0,
             services=[{
                 'name': 'web',
                 'image': 'busybox:latest',
@@ -754,7 +755,7 @@ class ProjectTest(DockerClientTestCase):
         vol_name = '{0:x}'.format(random.getrandbits(32))
         full_vol_name = 'composetest_{0}'.format(vol_name)
         config_data = config.Config(
-            version=2,
+            version=V2_0,
             services=[{
                 'name': 'web',
                 'image': 'busybox:latest',
@@ -779,7 +780,7 @@ class ProjectTest(DockerClientTestCase):
         vol_name = '{0:x}'.format(random.getrandbits(32))
 
         config_data = config.Config(
-            version=2,
+            version=V2_0,
             services=[{
                 'name': 'web',
                 'image': 'busybox:latest',
@@ -802,7 +803,7 @@ class ProjectTest(DockerClientTestCase):
         full_vol_name = 'composetest_{0}'.format(vol_name)
 
         config_data = config.Config(
-            version=2,
+            version=V2_0,
             services=[{
                 'name': 'web',
                 'image': 'busybox:latest',
@@ -841,7 +842,7 @@ class ProjectTest(DockerClientTestCase):
         full_vol_name = 'composetest_{0}'.format(vol_name)
         self.client.create_volume(vol_name)
         config_data = config.Config(
-            version=2,
+            version=V2_0,
             services=[{
                 'name': 'web',
                 'image': 'busybox:latest',
@@ -866,7 +867,7 @@ class ProjectTest(DockerClientTestCase):
         vol_name = '{0:x}'.format(random.getrandbits(32))
 
         config_data = config.Config(
-            version=2,
+            version=V2_0,
             services=[{
                 'name': 'web',
                 'image': 'busybox:latest',
@@ -895,7 +896,7 @@ class ProjectTest(DockerClientTestCase):
         base_file = config.ConfigFile(
             'base.yml',
             {
-                'version': 2,
+                'version': V2_0,
                 'services': {
                     'simple': {
                         'image': 'busybox:latest',

+ 4 - 2
tests/integration/testcases.py

@@ -10,6 +10,8 @@ from pytest import skip
 from .. import unittest
 from compose.cli.docker_client import docker_client
 from compose.config.config import resolve_environment
+from compose.config.config import V1
+from compose.config.config import V2_0
 from compose.const import API_VERSIONS
 from compose.const import LABEL_PROJECT
 from compose.progress_stream import stream_output
@@ -54,9 +56,9 @@ class DockerClientTestCase(unittest.TestCase):
     @classmethod
     def setUpClass(cls):
         if engine_version_too_low_for_v2():
-            version = API_VERSIONS[1]
+            version = API_VERSIONS[V1]
         else:
-            version = API_VERSIONS[2]
+            version = API_VERSIONS[V2_0]
 
         cls.client = docker_client(version)
 

+ 78 - 31
tests/unit/config/config_test.py

@@ -14,14 +14,15 @@ import pytest
 from compose.config import config
 from compose.config.config import resolve_build_args
 from compose.config.config import resolve_environment
+from compose.config.config import V1
+from compose.config.config import V2_0
 from compose.config.errors import ConfigurationError
 from compose.config.types import VolumeSpec
 from compose.const import IS_WINDOWS_PLATFORM
 from tests import mock
 from tests import unittest
 
-DEFAULT_VERSION = V2 = 2
-V1 = 1
+DEFAULT_VERSION = V2_0
 
 
 def make_service_dict(name, service_dict, working_dir, filename=None):
@@ -78,7 +79,7 @@ class ConfigTest(unittest.TestCase):
     def test_load_v2(self):
         config_data = config.load(
             build_config_details({
-                'version': 2,
+                'version': '2',
                 'services': {
                     'foo': {'image': 'busybox'},
                     'bar': {'image': 'busybox', 'environment': ['FOO=1']},
@@ -143,9 +144,55 @@ class ConfigTest(unittest.TestCase):
             }
         })
 
+    def test_valid_versions(self):
+        for version in ['2', '2.0']:
+            cfg = config.load(build_config_details({'version': version}))
+            assert cfg.version == V2_0
+
+    def test_v1_file_version(self):
+        cfg = config.load(build_config_details({'web': {'image': 'busybox'}}))
+        assert cfg.version == V1
+        assert list(s['name'] for s in cfg.services) == ['web']
+
+        cfg = config.load(build_config_details({'version': {'image': 'busybox'}}))
+        assert cfg.version == V1
+        assert list(s['name'] for s in cfg.services) == ['version']
+
+    def test_wrong_version_type(self):
+        for version in [None, 2, 2.0]:
+            with pytest.raises(ConfigurationError):
+                config.load(
+                    build_config_details(
+                        {'version': version},
+                        filename='filename.yml',
+                    )
+                )
+
+    def test_unsupported_version(self):
+        with pytest.raises(ConfigurationError):
+            config.load(
+                build_config_details(
+                    {'version': '2.1'},
+                    filename='filename.yml',
+                )
+            )
+
+    def test_v1_file_with_version_is_invalid(self):
+        for version in [1, "1"]:
+            with pytest.raises(ConfigurationError):
+                config.load(
+                    build_config_details(
+                        {
+                            'version': version,
+                            'web': {'image': 'busybox'},
+                        },
+                        filename='filename.yml',
+                    )
+                )
+
     def test_named_volume_config_empty(self):
         config_details = build_config_details({
-            'version': 2,
+            'version': '2',
             'services': {
                 'simple': {'image': 'busybox'}
             },
@@ -214,7 +261,7 @@ class ConfigTest(unittest.TestCase):
         with self.assertRaises(ConfigurationError):
             config.load(
                 build_config_details(
-                    {'version': 2, 'services': {'web': 'busybox:latest'}},
+                    {'version': '2', 'services': {'web': 'busybox:latest'}},
                     'working_dir',
                     'filename.yml'
                 )
@@ -224,7 +271,7 @@ class ConfigTest(unittest.TestCase):
         with self.assertRaises(ConfigurationError):
             config.load(
                 build_config_details({
-                    'version': 2,
+                    'version': '2',
                     'services': {'web': 'busybox:latest'},
                     'networks': {
                         'invalid': {'foo', 'bar'}
@@ -246,7 +293,7 @@ class ConfigTest(unittest.TestCase):
             with pytest.raises(ConfigurationError) as exc:
                 config.load(
                     build_config_details({
-                        'version': 2,
+                        'version': '2',
                         'services': {invalid_name: {'image': 'busybox'}}
                     }, 'working_dir', 'filename.yml')
                 )
@@ -256,7 +303,7 @@ class ConfigTest(unittest.TestCase):
         with pytest.raises(ConfigurationError) as exc:
             config.load(build_config_details(
                 {
-                    'version': 2,
+                    'version': '2',
                     'services': {
                         'web': {'image': 'busybox', 'name': 'bogus'},
                     }
@@ -307,7 +354,7 @@ class ConfigTest(unittest.TestCase):
             config.load(
                 build_config_details(
                     {
-                        'version': 2,
+                        'version': '2',
                         'services': {1: {'image': 'busybox'}}
                     },
                     'working_dir',
@@ -370,7 +417,7 @@ class ConfigTest(unittest.TestCase):
     def test_load_with_multiple_files_and_empty_override_v2(self):
         base_file = config.ConfigFile(
             'base.yml',
-            {'version': 2, 'services': {'web': {'image': 'example/web'}}})
+            {'version': '2', 'services': {'web': {'image': 'example/web'}}})
         override_file = config.ConfigFile('override.yml', None)
         details = config.ConfigDetails('.', [base_file, override_file])
 
@@ -394,7 +441,7 @@ class ConfigTest(unittest.TestCase):
         base_file = config.ConfigFile('base.yml', None)
         override_file = config.ConfigFile(
             'override.tml',
-            {'version': 2, 'services': {'web': {'image': 'example/web'}}}
+            {'version': '2', 'services': {'web': {'image': 'example/web'}}}
         )
         details = config.ConfigDetails('.', [base_file, override_file])
         with pytest.raises(ConfigurationError) as exc:
@@ -494,7 +541,7 @@ class ConfigTest(unittest.TestCase):
             config.load(
                 build_config_details(
                     {
-                        'version': 2,
+                        'version': '2',
                         'services': {
                             'web': {
                                 'build': '.',
@@ -509,7 +556,7 @@ class ConfigTest(unittest.TestCase):
 
         service = config.load(
             build_config_details({
-                'version': 2,
+                'version': '2',
                 'services': {
                     'web': {
                         'build': '.'
@@ -522,7 +569,7 @@ class ConfigTest(unittest.TestCase):
         service = config.load(
             build_config_details(
                 {
-                    'version': 2,
+                    'version': '2',
                     'services': {
                         'web': {
                             'build': {
@@ -543,7 +590,7 @@ class ConfigTest(unittest.TestCase):
         base_file = config.ConfigFile(
             'base.yaml',
             {
-                'version': 2,
+                'version': '2',
                 'services': {
                     'web': {
                         'image': 'example/web',
@@ -556,7 +603,7 @@ class ConfigTest(unittest.TestCase):
         override_file = config.ConfigFile(
             'override.yaml',
             {
-                'version': 2,
+                'version': '2',
                 'services': {
                     'web': {
                         'build': '/',
@@ -585,7 +632,7 @@ class ConfigTest(unittest.TestCase):
         base_file = config.ConfigFile(
             'base.yaml',
             {
-                'version': 2,
+                'version': '2',
                 'services': {
                     'web': {
                         'image': 'busybox:latest',
@@ -601,7 +648,7 @@ class ConfigTest(unittest.TestCase):
         base_file = config.ConfigFile(
             'base.yaml',
             {
-                'version': 2,
+                'version': '2',
                 'services': {
                     'web': {
                         'image': 'busybox:latest',
@@ -681,7 +728,7 @@ class ConfigTest(unittest.TestCase):
             config.load(
                 build_config_details(
                     {
-                        'version': 2,
+                        'version': '2',
                         'services': {
                             'foo': {'image': 1},
                         },
@@ -1016,7 +1063,7 @@ class ConfigTest(unittest.TestCase):
 
     def test_external_volume_config(self):
         config_details = build_config_details({
-            'version': 2,
+            'version': '2',
             'services': {
                 'bogus': {'image': 'busybox'}
             },
@@ -1034,7 +1081,7 @@ class ConfigTest(unittest.TestCase):
 
     def test_external_volume_invalid_config(self):
         config_details = build_config_details({
-            'version': 2,
+            'version': '2',
             'services': {
                 'bogus': {'image': 'busybox'}
             },
@@ -1047,7 +1094,7 @@ class ConfigTest(unittest.TestCase):
 
     def test_depends_on_orders_services(self):
         config_details = build_config_details({
-            'version': 2,
+            'version': '2',
             'services': {
                 'one': {'image': 'busybox', 'depends_on': ['three', 'two']},
                 'two': {'image': 'busybox', 'depends_on': ['three']},
@@ -1062,7 +1109,7 @@ class ConfigTest(unittest.TestCase):
 
     def test_depends_on_unknown_service_errors(self):
         config_details = build_config_details({
-            'version': 2,
+            'version': '2',
             'services': {
                 'one': {'image': 'busybox', 'depends_on': ['three']},
             },
@@ -1075,7 +1122,7 @@ class ConfigTest(unittest.TestCase):
 class NetworkModeTest(unittest.TestCase):
     def test_network_mode_standard(self):
         config_data = config.load(build_config_details({
-            'version': 2,
+            'version': '2',
             'services': {
                 'web': {
                     'image': 'busybox',
@@ -1101,7 +1148,7 @@ class NetworkModeTest(unittest.TestCase):
 
     def test_network_mode_container(self):
         config_data = config.load(build_config_details({
-            'version': 2,
+            'version': '2',
             'services': {
                 'web': {
                     'image': 'busybox',
@@ -1126,7 +1173,7 @@ class NetworkModeTest(unittest.TestCase):
 
     def test_network_mode_service(self):
         config_data = config.load(build_config_details({
-            'version': 2,
+            'version': '2',
             'services': {
                 'web': {
                     'image': 'busybox',
@@ -1160,7 +1207,7 @@ class NetworkModeTest(unittest.TestCase):
     def test_network_mode_service_nonexistent(self):
         with pytest.raises(ConfigurationError) as excinfo:
             config.load(build_config_details({
-                'version': 2,
+                'version': '2',
                 'services': {
                     'web': {
                         'image': 'busybox',
@@ -1175,7 +1222,7 @@ class NetworkModeTest(unittest.TestCase):
     def test_network_mode_plus_networks_is_invalid(self):
         with pytest.raises(ConfigurationError) as excinfo:
             config.load(build_config_details({
-                'version': 2,
+                'version': '2',
                 'services': {
                     'web': {
                         'image': 'busybox',
@@ -2202,7 +2249,7 @@ class ExtendsTest(unittest.TestCase):
         tmpdir = py.test.ensuretemp('test_extends_with_mixed_version')
         self.addCleanup(tmpdir.remove)
         tmpdir.join('docker-compose.yml').write("""
-            version: 2
+            version: "2"
             services:
               web:
                 extends:
@@ -2224,7 +2271,7 @@ class ExtendsTest(unittest.TestCase):
         tmpdir = py.test.ensuretemp('test_extends_with_defined_version')
         self.addCleanup(tmpdir.remove)
         tmpdir.join('docker-compose.yml').write("""
-            version: 2
+            version: "2"
             services:
               web:
                 extends:
@@ -2233,7 +2280,7 @@ class ExtendsTest(unittest.TestCase):
                 image: busybox
         """)
         tmpdir.join('base.yml').write("""
-            version: 2
+            version: "2"
             services:
                 base:
                   volumes: ['/foo']

+ 8 - 8
tests/unit/config/types_test.py

@@ -3,13 +3,13 @@ from __future__ import unicode_literals
 
 import pytest
 
+from compose.config.config import V1
+from compose.config.config import V2_0
 from compose.config.errors import ConfigurationError
 from compose.config.types import parse_extra_hosts
 from compose.config.types import VolumeFromSpec
 from compose.config.types import VolumeSpec
 from compose.const import IS_WINDOWS_PLATFORM
-from tests.unit.config.config_test import V1
-from tests.unit.config.config_test import V2
 
 
 def test_parse_extra_hosts_list():
@@ -91,26 +91,26 @@ class TestVolumesFromSpec(object):
             VolumeFromSpec.parse('unknown:format:ro', self.services, V1)
 
     def test_parse_v2_from_service(self):
-        volume_from = VolumeFromSpec.parse('servicea', self.services, V2)
+        volume_from = VolumeFromSpec.parse('servicea', self.services, V2_0)
         assert volume_from == VolumeFromSpec('servicea', 'rw', 'service')
 
     def test_parse_v2_from_service_with_mode(self):
-        volume_from = VolumeFromSpec.parse('servicea:ro', self.services, V2)
+        volume_from = VolumeFromSpec.parse('servicea:ro', self.services, V2_0)
         assert volume_from == VolumeFromSpec('servicea', 'ro', 'service')
 
     def test_parse_v2_from_container(self):
-        volume_from = VolumeFromSpec.parse('container:foo', self.services, V2)
+        volume_from = VolumeFromSpec.parse('container:foo', self.services, V2_0)
         assert volume_from == VolumeFromSpec('foo', 'rw', 'container')
 
     def test_parse_v2_from_container_with_mode(self):
-        volume_from = VolumeFromSpec.parse('container:foo:ro', self.services, V2)
+        volume_from = VolumeFromSpec.parse('container:foo:ro', self.services, V2_0)
         assert volume_from == VolumeFromSpec('foo', 'ro', 'container')
 
     def test_parse_v2_invalid_type(self):
         with pytest.raises(ConfigurationError) as exc:
-            VolumeFromSpec.parse('bogus:foo:ro', self.services, V2)
+            VolumeFromSpec.parse('bogus:foo:ro', self.services, V2_0)
         assert "Unknown volumes_from type 'bogus'" in exc.exconly()
 
     def test_parse_v2_invalid(self):
         with pytest.raises(ConfigurationError):
-            VolumeFromSpec.parse('unknown:format:ro', self.services, V2)
+            VolumeFromSpec.parse('unknown:format:ro', self.services, V2_0)