diff options
author | Joffrey F <f.joffrey@gmail.com> | 2018-03-28 11:45:04 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-28 11:45:04 -0700 |
commit | 8d96980ba4d2d28d2447fa9368193cd019a79cbb (patch) | |
tree | 92155f290741ae9fe91638fddae6ab6047c1973a | |
parent | 46191fe07b5f43e5d13b75d1dc85163f31d363ff (diff) | |
parent | 90c57f99e88c5caf4e4959b3740df7235a0e1220 (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.py | 12 | ||||
-rw-r--r-- | tests/unit/config/config_test.py | 16 |
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({ |