Skip to content

Commit

Permalink
On load error, retry reading the file with UTF-8 encoding
Browse files Browse the repository at this point in the history
Signed-off-by: Joffrey F <joffrey@docker.com>
  • Loading branch information
shin- committed Mar 27, 2018
1 parent 7e787a8 commit 90c57f9
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 3 deletions.
12 changes: 9 additions & 3 deletions compose/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from __future__ import unicode_literals

import functools
import io
import logging
import os
import string
Expand Down Expand Up @@ -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))
16 changes: 16 additions & 0 deletions tests/unit/config/config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import print_function
from __future__ import unicode_literals

import codecs
import os
import shutil
import tempfile
Expand Down Expand Up @@ -1623,6 +1624,21 @@ def test_load_yaml_with_yaml_error(self):

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({
Expand Down

0 comments on commit 90c57f9

Please sign in to comment.