From 6d2658ea65bc01655d0615bdb8d023e1982ca681 Mon Sep 17 00:00:00 2001 From: Ulysses Souza Date: Thu, 16 Jan 2020 09:51:58 +0100 Subject: [PATCH] Add python-dotenv Signed-off-by: Ulysses Souza --- compose/config/environment.py | 16 +++--------- requirements.txt | 1 + tests/unit/config/environment_test.py | 37 +++++++++++++++------------ 3 files changed, 24 insertions(+), 30 deletions(-) diff --git a/compose/config/environment.py b/compose/config/environment.py index 696356f32..6afbfc972 100644 --- a/compose/config/environment.py +++ b/compose/config/environment.py @@ -1,12 +1,11 @@ from __future__ import absolute_import from __future__ import unicode_literals -import codecs -import contextlib import logging import os import re +import dotenv import six from ..const import IS_WINDOWS_PLATFORM @@ -39,17 +38,8 @@ def env_vars_from_file(filename): raise EnvFileNotFound("Couldn't find env file: {}".format(filename)) elif not os.path.isfile(filename): raise EnvFileNotFound("{} is not a file.".format(filename)) - env = {} - with contextlib.closing(codecs.open(filename, 'r', 'utf-8-sig')) as fileobj: - for line in fileobj: - line = line.strip() - if line and not line.startswith('#'): - try: - k, v = split_env(line) - env[k] = v - except ConfigurationError as e: - raise ConfigurationError('In file {}: {}'.format(filename, e.msg)) - return env + + return dotenv.dotenv_values(dotenv_path=filename, encoding='utf-8-sig') class Environment(dict): diff --git a/requirements.txt b/requirements.txt index 76556d652..ee57c26b5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,6 +17,7 @@ paramiko==2.7.1 pypiwin32==219; sys_platform == 'win32' and python_version < '3.6' pypiwin32==223; sys_platform == 'win32' and python_version >= '3.6' PySocks==1.7.1 +python-dotenv==0.10.5 PyYAML==5.3 requests==2.22.0 six==1.12.0 diff --git a/tests/unit/config/environment_test.py b/tests/unit/config/environment_test.py index 186702db1..7e394d248 100644 --- a/tests/unit/config/environment_test.py +++ b/tests/unit/config/environment_test.py @@ -8,15 +8,18 @@ import os import shutil import tempfile -import pytest +from ddt import data +from ddt import ddt +from ddt import unpack from compose.config.environment import env_vars_from_file from compose.config.environment import Environment -from compose.config.errors import ConfigurationError from tests import unittest +@ddt class EnvironmentTest(unittest.TestCase): + @classmethod def test_get_simple(self): env = Environment({ 'FOO': 'bar', @@ -28,12 +31,14 @@ class EnvironmentTest(unittest.TestCase): assert env.get('BAR') == '1' assert env.get('BAZ') == '' + @classmethod def test_get_undefined(self): env = Environment({ 'FOO': 'bar' }) assert env.get('FOOBAR') is None + @classmethod def test_get_boolean(self): env = Environment({ 'FOO': '', @@ -48,20 +53,18 @@ class EnvironmentTest(unittest.TestCase): assert env.get_boolean('FOOBAR') is True assert env.get_boolean('UNDEFINED') is False - def test_env_vars_from_file_bom(self): + @data( + ('unicode exclude test', '\ufeffPARK_BOM=박봄\n', {'PARK_BOM': '박봄'}), + ('export prefixed test', 'export PREFIXED_VARS=yes\n', {"PREFIXED_VARS": "yes"}), + ('quoted vars test', "QUOTED_VARS='yes'\n", {"QUOTED_VARS": "yes"}), + ('double quoted vars test', 'DOUBLE_QUOTED_VARS="yes"\n', {"DOUBLE_QUOTED_VARS": "yes"}), + ('extra spaces test', 'SPACES_VARS = "yes"\n', {"SPACES_VARS": "yes"}), + ) + @unpack + def test_env_vars(self, test_name, content, expected): 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(os.path.join(tmpdir, 'bom.env'))) == { - 'PARK_BOM': '박봄' - } - - def test_env_vars_from_file_whitespace(self): - 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(os.path.join(tmpdir, 'whitespace.env'))) - assert 'environment variable' in exc.exconly() + file_abs_path = str(os.path.join(tmpdir, ".env")) + with codecs.open(file_abs_path, 'w', encoding='utf-8') as f: + f.write(content) + assert env_vars_from_file(file_abs_path) == expected, '"{}" Failed'.format(test_name)