mirror of
https://github.com/jupyterhub/the-littlest-jupyterhub.git
synced 2025-12-18 21:54:05 +08:00
consolidate yaml configuration
workaround ruamel.yaml issue 255,
where once an empty dict or list has been written,
'flow' style is used thereafter, using dense `{key: value}` form
instead of traditional yaml block style.
This commit is contained in:
19
tests/test_yaml.py
Normal file
19
tests/test_yaml.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from tljh.yaml import yaml
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_empty_flow(tmpdir):
|
||||||
|
path = tmpdir.join("config.yaml")
|
||||||
|
with path.open("w") as f:
|
||||||
|
f.write("{}")
|
||||||
|
# load empty config file
|
||||||
|
with path.open("r") as f:
|
||||||
|
config = yaml.load(f)
|
||||||
|
# set a value
|
||||||
|
config["key"] = "value"
|
||||||
|
# write to a file
|
||||||
|
with path.open("w") as f:
|
||||||
|
yaml.dump(config, f)
|
||||||
|
# verify that it didn't use compact '{}' flow-style
|
||||||
|
with path.open("r") as f:
|
||||||
|
content = f.read()
|
||||||
|
assert content.strip() == "key: value"
|
||||||
@@ -13,14 +13,13 @@ tljh-config show firstlevel.second_level
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
from collections import Sequence, Mapping
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from ruamel.yaml import YAML
|
from .yaml import yaml
|
||||||
from ruamel.yaml.comments import CommentedMap, CommentedSeq
|
|
||||||
yaml = YAML(typ='rt')
|
|
||||||
|
|
||||||
|
|
||||||
INSTALL_PREFIX = os.environ.get('TLJH_INSTALL_PREFIX', '/opt/tljh')
|
INSTALL_PREFIX = os.environ.get('TLJH_INSTALL_PREFIX', '/opt/tljh')
|
||||||
@@ -211,11 +210,11 @@ def parse_value(value_str):
|
|||||||
|
|
||||||
|
|
||||||
def _is_dict(item):
|
def _is_dict(item):
|
||||||
return isinstance(item, (dict, CommentedMap))
|
return isinstance(item, Mapping)
|
||||||
|
|
||||||
|
|
||||||
def _is_list(item):
|
def _is_list(item):
|
||||||
return isinstance(item, (list, CommentedSeq))
|
return isinstance(item, Sequence)
|
||||||
|
|
||||||
|
|
||||||
def main(argv=None):
|
def main(argv=None):
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ from urllib.error import HTTPError
|
|||||||
from urllib.request import urlopen, URLError
|
from urllib.request import urlopen, URLError
|
||||||
|
|
||||||
import pluggy
|
import pluggy
|
||||||
from ruamel.yaml import YAML
|
|
||||||
|
|
||||||
from tljh import (
|
from tljh import (
|
||||||
apt,
|
apt,
|
||||||
@@ -23,8 +22,7 @@ from tljh import (
|
|||||||
traefik,
|
traefik,
|
||||||
user,
|
user,
|
||||||
)
|
)
|
||||||
|
from .config import (
|
||||||
from tljh.config import (
|
|
||||||
CONFIG_DIR,
|
CONFIG_DIR,
|
||||||
CONFIG_FILE,
|
CONFIG_FILE,
|
||||||
HUB_ENV_PREFIX,
|
HUB_ENV_PREFIX,
|
||||||
@@ -32,10 +30,10 @@ from tljh.config import (
|
|||||||
STATE_DIR,
|
STATE_DIR,
|
||||||
USER_ENV_PREFIX,
|
USER_ENV_PREFIX,
|
||||||
)
|
)
|
||||||
|
from .yaml import yaml
|
||||||
|
|
||||||
HERE = os.path.abspath(os.path.dirname(__file__))
|
HERE = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
rt_yaml = YAML()
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -263,7 +261,7 @@ def ensure_admins(admins):
|
|||||||
config_path = CONFIG_FILE
|
config_path = CONFIG_FILE
|
||||||
if os.path.exists(config_path):
|
if os.path.exists(config_path):
|
||||||
with open(config_path, 'r') as f:
|
with open(config_path, 'r') as f:
|
||||||
config = rt_yaml.load(f)
|
config = yaml.load(f)
|
||||||
else:
|
else:
|
||||||
config = {}
|
config = {}
|
||||||
|
|
||||||
@@ -271,7 +269,7 @@ def ensure_admins(admins):
|
|||||||
config['users']['admin'] = list(admins)
|
config['users']['admin'] = list(admins)
|
||||||
|
|
||||||
with open(config_path, 'w+') as f:
|
with open(config_path, 'w+') as f:
|
||||||
rt_yaml.dump(config, f)
|
yaml.dump(config, f)
|
||||||
|
|
||||||
|
|
||||||
def ensure_jupyterhub_running(times=4):
|
def ensure_jupyterhub_running(times=4):
|
||||||
@@ -388,7 +386,7 @@ def ensure_config_yaml(plugin_manager):
|
|||||||
|
|
||||||
if os.path.exists(CONFIG_FILE):
|
if os.path.exists(CONFIG_FILE):
|
||||||
with open(CONFIG_FILE, 'r') as f:
|
with open(CONFIG_FILE, 'r') as f:
|
||||||
config = rt_yaml.load(f)
|
config = yaml.load(f)
|
||||||
else:
|
else:
|
||||||
config = {}
|
config = {}
|
||||||
|
|
||||||
@@ -396,7 +394,7 @@ def ensure_config_yaml(plugin_manager):
|
|||||||
hook.tljh_config_post_install(config=config)
|
hook.tljh_config_post_install(config=config)
|
||||||
|
|
||||||
with open(CONFIG_FILE, 'w+') as f:
|
with open(CONFIG_FILE, 'w+') as f:
|
||||||
rt_yaml.dump(config, f)
|
yaml.dump(config, f)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
32
tljh/yaml.py
Normal file
32
tljh/yaml.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
"""consolidated yaml API
|
||||||
|
|
||||||
|
ensures the same yaml settings for reading/writing
|
||||||
|
throughout tljh
|
||||||
|
"""
|
||||||
|
from ruamel.yaml.composer import Composer
|
||||||
|
from ruamel.yaml import YAML
|
||||||
|
|
||||||
|
|
||||||
|
class _NoEmptyFlowComposer(Composer):
|
||||||
|
"""yaml composer that avoids setting flow_style on empty
|
||||||
|
containers.
|
||||||
|
|
||||||
|
workaround ruamel.yaml issue #255
|
||||||
|
"""
|
||||||
|
|
||||||
|
def compose_mapping_node(self, anchor):
|
||||||
|
node = super().compose_mapping_node(anchor)
|
||||||
|
if not node.value:
|
||||||
|
node.flow_style = False
|
||||||
|
return node
|
||||||
|
|
||||||
|
def compose_sequence_node(self, anchor):
|
||||||
|
node = super().compose_sequence_node(anchor)
|
||||||
|
if not node.value:
|
||||||
|
node.flow_style = False
|
||||||
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
# create the global yaml object:
|
||||||
|
yaml = YAML(typ="rt")
|
||||||
|
yaml.Composer = _NoEmptyFlowComposer
|
||||||
Reference in New Issue
Block a user