summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoffrey F <f.joffrey@gmail.com>2018-03-28 11:45:04 -0700
committerGitHub <noreply@github.com>2018-03-28 11:45:04 -0700
commit8d96980ba4d2d28d2447fa9368193cd019a79cbb (patch)
tree92155f290741ae9fe91638fddae6ab6047c1973a
parent46191fe07b5f43e5d13b75d1dc85163f31d363ff (diff)
parent90c57f99e88c5caf4e4959b3740df7235a0e1220 (diff)
Merge pull request #5833 from docker/5826-load_retry_utf8
On load error, retry reading the file with UTF-8 encoding
-rw-r--r--compose/config/config.py12
-rw-r--r--tests/unit/config/config_test.py16
2 files changed, 25 insertions, 3 deletions
diff --git a/compose/config/config.py b/compose/config/config.py
index 7bc220e5..147c1d31 100644
--- a/compose/config/config.py
+++ b/compose/config/config.py
@@ -2,6 +2,7 @@ from __future__ import absolute_import
from __future__ import unicode_literals
import functools
+import io
import logging
import os
import string
@@ -1431,10 +1432,15 @@ def has_uppercase(name):
return any(char in string.ascii_uppercase for char in name)
-def load_yaml(filename):
+def load_yaml(filename, encoding=None):
try:
- with open(filename, 'r') as fh:
+ with io.open(filename, 'r', encoding=encoding) as fh:
return yaml.safe_load(fh)
- except (IOError, yaml.YAMLError) as e:
+ except (IOError, yaml.YAMLError, UnicodeDecodeError) as e:
+ if encoding is None:
+ # Sometimes the user's locale sets an encoding that doesn't match
+ # the YAML files. Im such cases, retry once with the "default"
+ # UTF-8 encoding
+ return load_yaml(filename, encoding='utf-8')
error_name = getattr(e, '__module__', '') + '.' + e.__class__.__name__
raise ConfigurationError(u"{}: {}".format(error_name, e))
diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py
index 7a9bb944..0574b215 100644
--- a/tests/unit/config/config_test.py
+++ b/tests/unit/config/config_test.py
@@ -3,6 +3,7 @@ from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
+import codecs
import os
import shutil
import tempfile
@@ -1623,6 +1624,21 @@ class ConfigTest(unittest.TestCase):
assert 'line 3, column 32' 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')
+ with codecs.open(str(bom_yaml), 'w', encoding='utf-8') as f:
+ f.write('''\ufeff
+ version: '2.3'
+ volumes:
+ park_bom:
+ ''')
+ assert config.load_yaml(str(bom_yaml)) == {
+ 'version': '2.3',
+ 'volumes': {'park_bom': None}
+ }
+
def test_validate_extra_hosts_invalid(self):
with pytest.raises(ConfigurationError) as exc:
config.load(build_config_details({