Blob Blame History Raw
From ea4d5276104e23b355c30be79df8cfa1c1781682 Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Tue, 27 Aug 2019 12:24:05 +0200
Subject: [PATCH 1/3] Move to the latest pytest versions for Python 2 and 3
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Lumír Balhar <lbalhar@redhat.com>
---
 requirements-dev.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/requirements-dev.txt b/requirements-dev.txt
index 27b71a268..5df32bfb5 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -2,5 +2,6 @@ coverage==4.4.2
 ddt==1.2.0
 flake8==3.5.0
 mock==3.0.5
-pytest==3.6.3
+pytest==5.1.1; python_version >= '3.5'
+pytest==4.6.5; python_version < '3.5'
 pytest-cov==2.5.1

From 899004290becf866b5dc890c8b498b92e41aee05 Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Tue, 27 Aug 2019 12:25:20 +0200
Subject: [PATCH 2/3] Implement custom context manager for changing CWD
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Lumír Balhar <lbalhar@redhat.com>
---
 tests/helpers.py | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/tests/helpers.py b/tests/helpers.py
index 327715ee2..1365c5bcf 100644
--- a/tests/helpers.py
+++ b/tests/helpers.py
@@ -1,6 +1,7 @@
 from __future__ import absolute_import
 from __future__ import unicode_literals
 
+import contextlib
 import os
 
 from compose.config.config import ConfigDetails
@@ -55,3 +56,17 @@ def create_host_file(client, filename):
         content = fh.read()
 
     return create_custom_host_file(client, filename, content)
+
+
+@contextlib.contextmanager
+def cd(path):
+    """
+    A context manager which changes the working directory to the given
+    path, and then changes it back to its previous value on exit.
+    """
+    prev_cwd = os.getcwd()
+    os.chdir(path)
+    try:
+        yield
+    finally:
+        os.chdir(prev_cwd)

From 297bfb332254848d7617e6dbfac62d64c92e3a10 Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Tue, 27 Aug 2019 12:26:01 +0200
Subject: [PATCH 3/3] Use stdlib modules instead of deprecated pytest fixtures
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Lumír Balhar <lbalhar@redhat.com>
---
 tests/acceptance/cli_test.py          |   8 +-
 tests/integration/project_test.py     |   8 +-
 tests/integration/state_test.py       |  29 ++-
 tests/unit/config/config_test.py      | 323 ++++++++++++++------------
 tests/unit/config/environment_test.py |  15 +-
 5 files changed, 204 insertions(+), 179 deletions(-)

diff --git a/tests/acceptance/cli_test.py b/tests/acceptance/cli_test.py
index 14dbb7d6c..9f8ff1fef 100644
--- a/tests/acceptance/cli_test.py
+++ b/tests/acceptance/cli_test.py
@@ -6,8 +6,10 @@
 import json
 import os.path
 import re
+import shutil
 import signal
 import subprocess
+import tempfile
 import time
 from collections import Counter
 from collections import namedtuple
@@ -844,9 +846,9 @@ def test_build_with_buildarg_old_api_version(self):
 
     def test_bundle_with_digests(self):
         self.base_dir = 'tests/fixtures/bundle-with-digests/'
-        tmpdir = pytest.ensuretemp('cli_test_bundle')
-        self.addCleanup(tmpdir.remove)
-        filename = str(tmpdir.join('example.dab'))
+        tmpdir = tempfile.mkdtemp('cli_test_bundle')
+        self.addCleanup(shutil.rmtree, tmpdir)
+        filename = os.path.join(tmpdir, 'example.dab')
 
         self.dispatch(['bundle', '--output', filename])
         with open(filename, 'r') as fh:
diff --git a/tests/integration/project_test.py b/tests/integration/project_test.py
index 4c88f3d6b..cb620a8c9 100644
--- a/tests/integration/project_test.py
+++ b/tests/integration/project_test.py
@@ -8,7 +8,6 @@
 import shutil
 import tempfile
 
-import py
 import pytest
 from docker.errors import APIError
 from docker.errors import NotFound
@@ -16,6 +15,7 @@
 from .. import mock
 from ..helpers import build_config as load_config
 from ..helpers import BUSYBOX_IMAGE_WITH_TAG
+from ..helpers import cd
 from ..helpers import create_host_file
 from .testcases import DockerClientTestCase
 from .testcases import SWARM_SKIP_CONTAINERS_ALL
@@ -1329,9 +1329,9 @@ def test_project_up_logging_with_multiple_files(self):
             })
         details = config.ConfigDetails('.', [base_file, override_file])
 
-        tmpdir = py.test.ensuretemp('logging_test')
-        self.addCleanup(tmpdir.remove)
-        with tmpdir.as_cwd():
+        tmpdir = tempfile.mkdtemp('logging_test')
+        self.addCleanup(shutil.rmtree, tmpdir)
+        with cd(tmpdir):
             config_data = config.load(details)
         project = Project.from_config(
             name='composetest', config_data=config_data, client=self.client
diff --git a/tests/integration/state_test.py b/tests/integration/state_test.py
index 714945ee5..492de7b8a 100644
--- a/tests/integration/state_test.py
+++ b/tests/integration/state_test.py
@@ -6,8 +6,10 @@
 from __future__ import unicode_literals
 
 import copy
+import os
+import shutil
+import tempfile
 
-import py
 from docker.errors import ImageNotFound
 
 from ..helpers import BUSYBOX_IMAGE_WITH_TAG
@@ -426,29 +428,32 @@ def safe_remove_image(image):
 
     @no_cluster('Can not guarantee the build will be run on the same node the service is deployed')
     def test_trigger_recreate_with_build(self):
-        context = py.test.ensuretemp('test_trigger_recreate_with_build')
-        self.addCleanup(context.remove)
+        context = tempfile.mkdtemp('test_trigger_recreate_with_build')
+        self.addCleanup(shutil.rmtree, context)
 
         base_image = "FROM busybox\nLABEL com.docker.compose.test_image=true\n"
-        dockerfile = context.join('Dockerfile')
-        dockerfile.write(base_image)
+        dockerfile = os.path.join(context, 'Dockerfile')
+        with open(dockerfile, mode="w") as dockerfile_fh:
+            dockerfile_fh.write(base_image)
 
         web = self.create_service('web', build={'context': str(context)})
         container = web.create_container()
 
-        dockerfile.write(base_image + 'CMD echo hello world\n')
+        with open(dockerfile, mode="w") as dockerfile_fh:
+            dockerfile_fh.write(base_image + 'CMD echo hello world\n')
         web.build()
 
         web = self.create_service('web', build={'context': str(context)})
         assert ('recreate', [container]) == web.convergence_plan()
 
     def test_image_changed_to_build(self):
-        context = py.test.ensuretemp('test_image_changed_to_build')
-        self.addCleanup(context.remove)
-        context.join('Dockerfile').write("""
-            FROM busybox
-            LABEL com.docker.compose.test_image=true
-        """)
+        context = tempfile.mkdtemp('test_image_changed_to_build')
+        self.addCleanup(shutil.rmtree, context)
+        with open(os.path.join(context, 'Dockerfile'), mode="w") as dockerfile:
+            dockerfile.write("""
+                FROM busybox
+                LABEL com.docker.compose.test_image=true
+            """)
 
         web = self.create_service('web', image='busybox')
         container = web.create_container()
diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py
index 5ad1a2334..4d3e6b4ab 100644
--- a/tests/unit/config/config_test.py
+++ b/tests/unit/config/config_test.py
@@ -10,12 +10,12 @@
 from operator import itemgetter
 from random import shuffle
 
-import py
 import pytest
 import yaml
 
 from ...helpers import build_config_details
 from ...helpers import BUSYBOX_IMAGE_WITH_TAG
+from ...helpers import cd
 from compose.config import config
 from compose.config import types
 from compose.config.config import resolve_build_args
@@ -776,13 +776,14 @@ def test_load_with_multiple_files_and_extends_in_override_file(self):
             })
         details = config.ConfigDetails('.', [base_file, override_file])
 
-        tmpdir = py.test.ensuretemp('config_test')
-        self.addCleanup(tmpdir.remove)
-        tmpdir.join('common.yml').write("""
-            base:
-              labels: ['label=one']
-        """)
-        with tmpdir.as_cwd():
+        tmpdir = tempfile.mkdtemp('config_test')
+        self.addCleanup(shutil.rmtree, tmpdir)
+        with open(os.path.join(tmpdir, 'common.yml'), mode="w") as common_fh:
+            common_fh.write("""
+                base:
+                  labels: ['label=one']
+            """)
+        with cd(tmpdir):
             service_dicts = config.load(details).services
 
         expected = [
@@ -811,19 +812,20 @@ def test_load_mixed_extends_resolution(self):
             }
         )
 
-        tmpdir = pytest.ensuretemp('config_test')
-        self.addCleanup(tmpdir.remove)
-        tmpdir.join('base.yml').write("""
-            version: '2.2'
-            services:
-              base:
-                image: base
-              web:
-                extends: base
-        """)
+        tmpdir = tempfile.mkdtemp('config_test')
+        self.addCleanup(shutil.rmtree, tmpdir)
+        with open(os.path.join(tmpdir, 'base.yml'), mode="w") as base_fh:
+            base_fh.write("""
+                version: '2.2'
+                services:
+                  base:
+                    image: base
+                  web:
+                    extends: base
+            """)
 
         details = config.ConfigDetails('.', [main_file])
-        with tmpdir.as_cwd():
+        with cd(tmpdir):
             service_dicts = config.load(details).services
             assert service_dicts[0] == {
                 'name': 'prodweb',
@@ -1761,22 +1763,23 @@ def test_config_valid_environment_dict_key_contains_dashes(self):
         assert services[0]['environment']['SPRING_JPA_HIBERNATE_DDL-AUTO'] == 'none'
 
     def test_load_yaml_with_yaml_error(self):
-        tmpdir = py.test.ensuretemp('invalid_yaml_test')
-        self.addCleanup(tmpdir.remove)
-        invalid_yaml_file = tmpdir.join('docker-compose.yml')
-        invalid_yaml_file.write("""
-            web:
-              this is bogus: ok: what
-        """)
+        tmpdir = tempfile.mkdtemp('invalid_yaml_test')
+        self.addCleanup(shutil.rmtree, tmpdir)
+        invalid_yaml_file = os.path.join(tmpdir, 'docker-compose.yml')
+        with open(invalid_yaml_file, mode="w") as invalid_yaml_file_fh:
+            invalid_yaml_file_fh.write("""
+                web:
+                  this is bogus: ok: what
+            """)
         with pytest.raises(ConfigurationError) as exc:
             config.load_yaml(str(invalid_yaml_file))
 
-        assert 'line 3, column 32' in exc.exconly()
+        assert 'line 3, column 36' in exc.exconly()
 
     def test_load_yaml_with_bom(self):
-        tmpdir = py.test.ensuretemp('bom_yaml')
-        self.addCleanup(tmpdir.remove)
-        bom_yaml = tmpdir.join('docker-compose.yml')
+        tmpdir = tempfile.mkdtemp('bom_yaml')
+        self.addCleanup(shutil.rmtree, tmpdir)
+        bom_yaml = os.path.join(tmpdir, 'docker-compose.yml')
         with codecs.open(str(bom_yaml), 'w', encoding='utf-8') as f:
             f.write('''\ufeff
                 version: '2.3'
@@ -4700,43 +4703,48 @@ def test_extended_service_with_verbose_and_shorthand_way(self):
 
     @mock.patch.dict(os.environ)
     def test_extends_with_environment_and_env_files(self):
-        tmpdir = py.test.ensuretemp('test_extends_with_environment')
-        self.addCleanup(tmpdir.remove)
-        commondir = tmpdir.mkdir('common')
-        commondir.join('base.yml').write("""
-            app:
-                image: 'example/app'
-                env_file:
-                    - 'envs'
-                environment:
-                    - SECRET
-                    - TEST_ONE=common
-                    - TEST_TWO=common
-        """)
-        tmpdir.join('docker-compose.yml').write("""
-            ext:
-                extends:
-                    file: common/base.yml
-                    service: app
-                env_file:
-                    - 'envs'
-                environment:
-                    - THING
-                    - TEST_ONE=top
-        """)
-        commondir.join('envs').write("""
-            COMMON_ENV_FILE
-            TEST_ONE=common-env-file
-            TEST_TWO=common-env-file
-            TEST_THREE=common-env-file
-            TEST_FOUR=common-env-file
-        """)
-        tmpdir.join('envs').write("""
-            TOP_ENV_FILE
-            TEST_ONE=top-env-file
-            TEST_TWO=top-env-file
-            TEST_THREE=top-env-file
-        """)
+        tmpdir = tempfile.mkdtemp('test_extends_with_environment')
+        self.addCleanup(shutil.rmtree, tmpdir)
+        commondir = os.path.join(tmpdir, 'common')
+        os.mkdir(commondir)
+        with open(os.path.join(commondir, 'base.yml'), mode="w") as base_fh:
+            base_fh.write("""
+                app:
+                    image: 'example/app'
+                    env_file:
+                        - 'envs'
+                    environment:
+                        - SECRET
+                        - TEST_ONE=common
+                        - TEST_TWO=common
+            """)
+        with open(os.path.join(tmpdir, 'docker-compose.yml'), mode="w") as docker_compose_fh:
+            docker_compose_fh.write("""
+                ext:
+                    extends:
+                        file: common/base.yml
+                        service: app
+                    env_file:
+                        - 'envs'
+                    environment:
+                        - THING
+                        - TEST_ONE=top
+            """)
+        with open(os.path.join(commondir, 'envs'), mode="w") as envs_fh:
+            envs_fh.write("""
+                COMMON_ENV_FILE
+                TEST_ONE=common-env-file
+                TEST_TWO=common-env-file
+                TEST_THREE=common-env-file
+                TEST_FOUR=common-env-file
+            """)
+        with open(os.path.join(tmpdir, 'envs'), mode="w") as envs_fh:
+            envs_fh.write("""
+                TOP_ENV_FILE
+                TEST_ONE=top-env-file
+                TEST_TWO=top-env-file
+                TEST_THREE=top-env-file
+            """)
 
         expected = [
             {
@@ -4759,72 +4767,77 @@ def test_extends_with_environment_and_env_files(self):
         os.environ['THING'] = 'thing'
         os.environ['COMMON_ENV_FILE'] = 'secret'
         os.environ['TOP_ENV_FILE'] = 'secret'
-        config = load_from_filename(str(tmpdir.join('docker-compose.yml')))
+        config = load_from_filename(str(os.path.join(tmpdir, 'docker-compose.yml')))
 
         assert config == expected
 
     def test_extends_with_mixed_versions_is_error(self):
-        tmpdir = py.test.ensuretemp('test_extends_with_mixed_version')
-        self.addCleanup(tmpdir.remove)
-        tmpdir.join('docker-compose.yml').write("""
-            version: "2"
-            services:
-              web:
-                extends:
-                  file: base.yml
-                  service: base
-                image: busybox
-        """)
-        tmpdir.join('base.yml').write("""
-            base:
-              volumes: ['/foo']
-              ports: ['3000:3000']
-        """)
+        tmpdir = tempfile.mkdtemp('test_extends_with_mixed_version')
+        self.addCleanup(shutil.rmtree, tmpdir)
+        with open(os.path.join(tmpdir, 'docker-compose.yml'), mode="w") as docker_compose_fh:
+            docker_compose_fh.write("""
+                version: "2"
+                services:
+                  web:
+                    extends:
+                      file: base.yml
+                      service: base
+                    image: busybox
+            """)
+        with open(os.path.join(tmpdir, 'base.yml'), mode="w") as base_fh:
+            base_fh.write("""
+                base:
+                  volumes: ['/foo']
+                  ports: ['3000:3000']
+            """)
 
         with pytest.raises(ConfigurationError) as exc:
-            load_from_filename(str(tmpdir.join('docker-compose.yml')))
+            load_from_filename(str(os.path.join(tmpdir, 'docker-compose.yml')))
         assert 'Version mismatch' in exc.exconly()
 
     def test_extends_with_defined_version_passes(self):
-        tmpdir = py.test.ensuretemp('test_extends_with_defined_version')
-        self.addCleanup(tmpdir.remove)
-        tmpdir.join('docker-compose.yml').write("""
-            version: "2"
-            services:
-              web:
-                extends:
-                  file: base.yml
-                  service: base
-                image: busybox
-        """)
-        tmpdir.join('base.yml').write("""
-            version: "2"
-            services:
-                base:
-                  volumes: ['/foo']
-                  ports: ['3000:3000']
-                  command: top
-        """)
-
-        service = load_from_filename(str(tmpdir.join('docker-compose.yml')))
+        tmpdir = tempfile.mkdtemp('test_extends_with_defined_version')
+        self.addCleanup(shutil.rmtree, tmpdir)
+        with open(os.path.join(tmpdir, 'docker-compose.yml'), mode="w") as docker_compose_fh:
+            docker_compose_fh.write("""
+                version: "2"
+                services:
+                  web:
+                    extends:
+                      file: base.yml
+                      service: base
+                    image: busybox
+            """)
+        with open(os.path.join(tmpdir, 'base.yml'), mode="w") as base_fh:
+            base_fh.write("""
+                version: "2"
+                services:
+                  base:
+                    volumes: ['/foo']
+                    ports: ['3000:3000']
+                    command: top
+            """)
+
+        service = load_from_filename(str(os.path.join(tmpdir, 'docker-compose.yml')))
         assert service[0]['command'] == "top"
 
     def test_extends_with_depends_on(self):
-        tmpdir = py.test.ensuretemp('test_extends_with_depends_on')
-        self.addCleanup(tmpdir.remove)
-        tmpdir.join('docker-compose.yml').write("""
-            version: "2"
-            services:
-              base:
-                image: example
-              web:
-                extends: base
-                image: busybox
-                depends_on: ['other']
-              other:
-                image: example
-        """)
-        services = load_from_filename(str(tmpdir.join('docker-compose.yml')))
+        tmpdir = tempfile.mkdtemp('test_extends_with_depends_on')
+        self.addCleanup(shutil.rmtree, tmpdir)
+        with open(os.path.join(tmpdir, 'docker-compose.yml'), mode="w") as docker_compose_fh:
+            docker_compose_fh.write("""
+                version: "2"
+                services:
+                  base:
+                    image: example
+                  web:
+                    extends: base
+                    image: busybox
+                    depends_on: ['other']
+                  other:
+                    image: example
+            """)
+        services = load_from_filename(str(os.path.join(tmpdir, 'docker-compose.yml')))
         assert service_sort(services)[2]['depends_on'] == {
             'other': {'condition': 'service_started'}
         }
@@ -4843,45 +4856,47 @@ def test_extends_with_healthcheck(self):
         }]
 
     def test_extends_with_ports(self):
-        tmpdir = py.test.ensuretemp('test_extends_with_ports')
-        self.addCleanup(tmpdir.remove)
-        tmpdir.join('docker-compose.yml').write("""
-            version: '2'
-
-            services:
-              a:
-                image: nginx
-                ports:
-                  - 80
-
-              b:
-                extends:
-                  service: a
-        """)
-        services = load_from_filename(str(tmpdir.join('docker-compose.yml')))
+        tmpdir = tempfile.mkdtemp('test_extends_with_ports')
+        self.addCleanup(shutil.rmtree, tmpdir)
+        with open(os.path.join(tmpdir, 'docker-compose.yml'), mode="w") as docker_compose_fh:
+            docker_compose_fh.write("""
+                version: '2'
+
+                services:
+                  a:
+                    image: nginx
+                    ports:
+                      - 80
+
+                  b:
+                    extends:
+                      service: a
+            """)
+        services = load_from_filename(str(os.path.join(tmpdir, 'docker-compose.yml')))
 
         assert len(services) == 2
         for svc in services:
             assert svc['ports'] == [types.ServicePort('80', None, None, None, None)]
 
     def test_extends_with_security_opt(self):
-        tmpdir = py.test.ensuretemp('test_extends_with_ports')
-        self.addCleanup(tmpdir.remove)
-        tmpdir.join('docker-compose.yml').write("""
-            version: '2'
-
-            services:
-              a:
-                image: nginx
-                security_opt:
-                  - apparmor:unconfined
-                  - seccomp:unconfined
-
-              b:
-                extends:
-                  service: a
-        """)
-        services = load_from_filename(str(tmpdir.join('docker-compose.yml')))
+        tmpdir = tempfile.mkdtemp('test_extends_with_ports')
+        self.addCleanup(shutil.rmtree, tmpdir)
+        with open(os.path.join(tmpdir, 'docker-compose.yml'), mode="w") as docker_compose_fh:
+            docker_compose_fh.write("""
+                version: '2'
+
+                services:
+                  a:
+                    image: nginx
+                    security_opt:
+                    - apparmor:unconfined
+                    - seccomp:unconfined
+
+                  b:
+                    extends:
+                      service: a
+            """)
+        services = load_from_filename(str(os.path.join(tmpdir, 'docker-compose.yml')))
         assert len(services) == 2
         for svc in services:
             assert types.SecurityOpt.parse('apparmor:unconfined') in svc['security_opt']
diff --git a/tests/unit/config/environment_test.py b/tests/unit/config/environment_test.py
index 88eb0d6e1..186702db1 100644
--- a/tests/unit/config/environment_test.py
+++ b/tests/unit/config/environment_test.py
@@ -4,6 +4,9 @@
 from __future__ import unicode_literals
 
 import codecs
+import os
+import shutil
+import tempfile
 
 import pytest
 
@@ -46,19 +49,19 @@ def test_get_boolean(self):
         assert env.get_boolean('UNDEFINED') is False
 
     def test_env_vars_from_file_bom(self):
-        tmpdir = pytest.ensuretemp('env_file')
-        self.addCleanup(tmpdir.remove)
+        tmpdir = tempfile.mkdtemp('env_file')
+        self.addCleanup(shutil.rmtree, tmpdir)
         with codecs.open('{}/bom.env'.format(str(tmpdir)), 'w', encoding='utf-8') as f:
             f.write('\ufeffPARK_BOM=박봄\n')
-        assert env_vars_from_file(str(tmpdir.join('bom.env'))) == {
+        assert env_vars_from_file(str(os.path.join(tmpdir, 'bom.env'))) == {
             'PARK_BOM': '박봄'
         }
 
     def test_env_vars_from_file_whitespace(self):
-        tmpdir = pytest.ensuretemp('env_file')
-        self.addCleanup(tmpdir.remove)
+        tmpdir = tempfile.mkdtemp('env_file')
+        self.addCleanup(shutil.rmtree, tmpdir)
         with codecs.open('{}/whitespace.env'.format(str(tmpdir)), 'w', encoding='utf-8') as f:
             f.write('WHITESPACE =yes\n')
         with pytest.raises(ConfigurationError) as exc:
-            env_vars_from_file(str(tmpdir.join('whitespace.env')))
+            env_vars_from_file(str(os.path.join(tmpdir, 'whitespace.env')))
         assert 'environment variable' in exc.exconly()