Merge pull request #3116 from maartenbreddels/directory_json

allow default json files in a .d directory
Min RK 8 years ago committed by GitHub
commit 9c7c213a47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,6 +1,6 @@
from notebook.auth import passwd
from getpass import getpass
from traitlets.config.manager import BaseJSONConfigManager
from notebook.config_manager import BaseJSONConfigManager
from jupyter_core.paths import jupyter_config_dir
import argparse
import sys

@ -5,10 +5,10 @@ import os
from ..extensions import BaseExtensionApp, _get_config_dir, GREEN_ENABLED, RED_DISABLED
from .._version import __version__
from notebook.config_manager import BaseJSONConfigManager
from jupyter_core.paths import jupyter_config_path
from traitlets.config.manager import BaseJSONConfigManager
from traitlets.utils.importstring import import_item
from traitlets import Bool

@ -15,10 +15,10 @@ except ImportError:
from ipython_genutils.tempdir import TemporaryDirectory
from ipython_genutils import py3compat
from traitlets.config.manager import BaseJSONConfigManager
from traitlets.tests.utils import check_help_all_output
import notebook.nbextensions as nbextensions
from notebook.config_manager import BaseJSONConfigManager
from ..bundlerextensions import (_get_config_dir, enable_bundler_python,
disable_bundler_python)

@ -0,0 +1,109 @@
# coding: utf-8
"""Manager to read and modify config data in JSON files."""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import errno
import glob
import io
import json
import os
from six import PY3
from traitlets.config import LoggingConfigurable
from traitlets.traitlets import Unicode, Bool
def recursive_update(target, new):
"""Recursively update one dictionary using another.
None values will delete their keys.
"""
for k, v in new.items():
if isinstance(v, dict):
if k not in target:
target[k] = {}
recursive_update(target[k], v)
if not target[k]:
# Prune empty subdicts
del target[k]
elif v is None:
target.pop(k, None)
else:
target[k] = v
class BaseJSONConfigManager(LoggingConfigurable):
"""General JSON config manager
Deals with persisting/storing config in a json file with optionally
default values in a {section_name}.d directory.
"""
config_dir = Unicode('.')
read_directory = Bool(True)
def ensure_config_dir_exists(self):
"""Will try to create the config_dir directory."""
try:
os.makedirs(self.config_dir, 0o755)
except OSError as e:
if e.errno != errno.EEXIST:
raise
def file_name(self, section_name):
"""Returns the json filename for the section_name: {config_dir}/{section_name}.json"""
return os.path.join(self.config_dir, section_name+'.json')
def directory(self, section_name):
"""Returns the directory name for the section name: {config_dir}/{section_name}.d"""
return os.path.join(self.config_dir, section_name+'.d')
def get(self, section_name):
"""Retrieve the config data for the specified section.
Returns the data as a dictionary, or an empty dictionary if the file
doesn't exist.
"""
paths = [self.file_name(section_name)]
if self.read_directory:
pattern = os.path.join(self.directory(section_name), '*.json')
# These json files should be processed first so that the
# {section_name}.json take precedence.
# The idea behind this is that installing a Python package may
# put a json file somewhere in the a .d directory, while the
# .json file is probably a user configuration.
paths = sorted(glob.glob(pattern)) + paths
self.log.debug('Paths used for configuration of %s: \n\t%s', section_name, '\n\t'.join(paths))
data = {}
for path in paths:
if os.path.isfile(path):
with io.open(path, encoding='utf-8') as f:
recursive_update(data, json.load(f))
return data
def set(self, section_name, data):
"""Store the given config data.
"""
filename = self.file_name(section_name)
self.ensure_config_dir_exists()
if PY3:
f = io.open(filename, 'w', encoding='utf-8')
else:
f = open(filename, 'wb')
with f:
json.dump(data, f, indent=2)
def update(self, section_name, new_data):
"""Modify the config section by recursively updating it with new_data.
Returns the modified config data as a dictionary.
"""
data = self.get(section_name)
recursive_update(data, new_data)
self.set(section_name, data)
return data

@ -28,8 +28,8 @@ from jupyter_core.utils import ensure_dir_exists
from ipython_genutils.py3compat import string_types, cast_unicode_py2
from ipython_genutils.tempdir import TemporaryDirectory
from ._version import __version__
from .config_manager import BaseJSONConfigManager
from traitlets.config.manager import BaseJSONConfigManager
from traitlets.utils.importstring import import_item
DEPRECATED_ARGUMENT = object()

@ -11,12 +11,12 @@ import sys
from jupyter_core.paths import jupyter_config_path
from ._version import __version__
from .config_manager import BaseJSONConfigManager
from .extensions import (
BaseExtensionApp, _get_config_dir, GREEN_ENABLED, RED_DISABLED, GREEN_OK, RED_X
)
from traitlets import Bool
from traitlets.utils.importstring import import_item
from traitlets.config.manager import BaseJSONConfigManager
# ------------------------------------------------------------------------------

@ -5,7 +5,7 @@
import os.path
from traitlets.config.manager import BaseJSONConfigManager, recursive_update
from notebook.config_manager import BaseJSONConfigManager, recursive_update
from jupyter_core.paths import jupyter_config_dir, jupyter_config_path
from traitlets import Unicode, Instance, List, observe, default
from traitlets.config import LoggingConfigurable

@ -0,0 +1,39 @@
import json
import os
import shutil
import tempfile
from notebook.config_manager import BaseJSONConfigManager
def test_json():
tmpdir = tempfile.mkdtemp()
try:
with open(os.path.join(tmpdir, 'foo.json'), 'w') as f:
json.dump(dict(a=1), f)
# also make a foo.d/ directory with multiple json files
os.makedirs(os.path.join(tmpdir, 'foo.d'))
with open(os.path.join(tmpdir, 'foo.d', 'a.json'), 'w') as f:
json.dump(dict(a=2, b=1), f)
with open(os.path.join(tmpdir, 'foo.d', 'b.json'), 'w') as f:
json.dump(dict(a=3, b=2, c=3), f)
manager = BaseJSONConfigManager(config_dir=tmpdir, read_directory=False)
data = manager.get('foo')
assert 'a' in data
assert 'b' not in data
assert 'c' not in data
assert data['a'] == 1
manager = BaseJSONConfigManager(config_dir=tmpdir, read_directory=True)
data = manager.get('foo')
assert 'a' in data
assert 'b' in data
assert 'c' in data
# files should be read in order foo.d/a.json foo.d/b.json foo.json
assert data['a'] == 1
assert data['b'] == 2
assert data['c'] == 3
finally:
shutil.rmtree(tmpdir)

@ -30,7 +30,7 @@ from notebook.nbextensions import (install_nbextension, check_nbextension,
validate_nbextension, validate_nbextension_python
)
from traitlets.config.manager import BaseJSONConfigManager
from notebook.config_manager import BaseJSONConfigManager
def touch(file_name, mtime=None):

@ -10,7 +10,7 @@ except ImportError:
from ipython_genutils.tempdir import TemporaryDirectory
from ipython_genutils import py3compat
from traitlets.config.manager import BaseJSONConfigManager
from notebook.config_manager import BaseJSONConfigManager
from traitlets.tests.utils import check_help_all_output
from jupyter_core import paths

Loading…
Cancel
Save