Support loading closed config file descriptor.

Refactored fix supplied in #735 and added tests.
This commit is contained in:
Waylan Limberg
2016-04-04 16:27:59 -04:00
parent 9a0451ae3e
commit 28cb2f349f
2 changed files with 82 additions and 2 deletions

View File

@@ -106,7 +106,11 @@ def _open_config_file(config_file):
if config_file is None:
config_file = os.path.abspath('mkdocs.yml')
log.debug("Loading configuration file: %s", config_file)
# If closed file descriptor, get file path to reopen later.
if hasattr(config_file, 'closed') and config_file.closed:
config_file = config_file.name
log.debug("Loading configuration file: {0}".format(config_file))
# If it is a string, we can assume it is a path and attempt to open it.
if isinstance(config_file, utils.string_types):
@@ -116,6 +120,9 @@ def _open_config_file(config_file):
raise exceptions.ConfigurationError(
"Config file '{0}' does not exist.".format(config_file))
# Ensure file descriptor is at begining
config_file.seek(0)
return config_file

View File

@@ -35,12 +35,85 @@ class ConfigBaseTests(unittest.TestCase):
self.assertEqual(len(warnings), 0)
def test_load_missing_required(self):
def test_load_from_file(self):
"""
Users can explicitly set the config file using the '--config' option.
Allows users to specify a config other than the default `mkdocs.yml`.
"""
config_file = tempfile.NamedTemporaryFile('w', delete=False)
try:
config_file.write("site_name: MkDocs Test\n")
config_file.flush()
config_file.close()
cfg = base.load_config(config_file=config_file.name)
self.assertIsInstance(cfg, base.Config)
self.assertEqual(cfg['site_name'], 'MkDocs Test')
finally:
os.remove(config_file.name)
def test_load_from_missing_file(self):
self.assertRaises(exceptions.ConfigurationError,
base.load_config, config_file='missing_file.yml')
def test_load_from_open_file(self):
"""
`load_config` can accept an open file descriptor.
"""
config_file = tempfile.NamedTemporaryFile('r+', delete=False)
try:
config_file.write("site_name: MkDocs Test\n")
config_file.flush()
cfg = base.load_config(config_file=config_file)
self.assertIsInstance(cfg, base.Config)
self.assertEqual(cfg['site_name'], 'MkDocs Test')
# load_config will always close the file
self.assertTrue(config_file.closed)
finally:
os.remove(config_file.name)
def test_load_from_closed_file(self):
"""
The `serve` command with auto-reload may pass in a closed file descriptor.
Ensure `load_config` reloads the closed file.
"""
config_file = tempfile.NamedTemporaryFile('w', delete=False)
try:
config_file.write("site_name: MkDocs Test\n")
config_file.flush()
config_file.close()
cfg = base.load_config(config_file=config_file)
self.assertIsInstance(cfg, base.Config)
self.assertEqual(cfg['site_name'], 'MkDocs Test')
finally:
os.remove(config_file.name)
def test_load_from_deleted_file(self):
"""
Deleting the config file could trigger a server reload.
"""
config_file = tempfile.NamedTemporaryFile('w', delete=False)
try:
config_file.write("site_name: MkDocs Test\n")
config_file.flush()
config_file.close()
finally:
os.remove(config_file.name)
self.assertRaises(exceptions.ConfigurationError,
base.load_config, config_file=config_file)
def test_load_missing_required(self):
"""
`site_name` is a required setting.
"""
config_file = tempfile.NamedTemporaryFile('w', delete=False)
try:
config_file.write(