osbuild-mpp: Support loading yaml as well as json files
yaml files are essentially compatible with json files, although they have some advantages, like allowing comments and being easier for humans to read/write. This changes the reading of the file to use a yaml parser instead of a json parser, but still produces json at the end. I tried manually converting a json file to yaml and running osbuild-mpp, and it produced an identical file. By default the yaml parser doesn't respect order so i had to tweak the loader a bit to use OrderedDict.
This commit is contained in:
parent
04423e8a6a
commit
52c3cb12ba
1 changed files with 44 additions and 5 deletions
|
|
@ -242,6 +242,7 @@ import collections
|
|||
import contextlib
|
||||
import hashlib
|
||||
import json
|
||||
import yaml
|
||||
import os
|
||||
import pathlib
|
||||
import string
|
||||
|
|
@ -257,6 +258,33 @@ import hawkey
|
|||
|
||||
from osbuild.util.rhsm import Subscriptions
|
||||
|
||||
class YamlOrderedLoader(yaml.Loader):
|
||||
def construct_mapping(self, node, deep=False):
|
||||
if not isinstance(node, yaml.MappingNode):
|
||||
raise ConstructorError(None, None,
|
||||
"expected a mapping node, but found %s" % node.id,
|
||||
node.start_mark)
|
||||
mapping = collections.OrderedDict()
|
||||
for key_node, value_node in node.value:
|
||||
key = self.construct_object(key_node, deep=deep)
|
||||
if not isinstance(key, collections.abc.Hashable):
|
||||
raise ConstructorError("while constructing a mapping", node.start_mark,
|
||||
"found unhashable key", key_node.start_mark)
|
||||
value = self.construct_object(value_node, deep=deep)
|
||||
mapping[key] = value
|
||||
return mapping
|
||||
def construct_yaml_map(self, node):
|
||||
data = collections.OrderedDict()
|
||||
yield data
|
||||
value = self.construct_mapping(node)
|
||||
data.update(value)
|
||||
yaml.add_constructor('tag:yaml.org,2002:map', YamlOrderedLoader.construct_yaml_map)
|
||||
|
||||
def yaml_load_ordered(source):
|
||||
return yaml.load(source, YamlOrderedLoader)
|
||||
|
||||
def json_load_ordered(source):
|
||||
return json.load(source, object_pairs_hook=collections.OrderedDict)
|
||||
|
||||
def element_enter(element, key, default):
|
||||
if key not in element:
|
||||
|
|
@ -603,11 +631,22 @@ class ManifestFile:
|
|||
@staticmethod
|
||||
def load_from_fd(f, path, overrides, default_vars):
|
||||
# We use OrderedDict to preserve key order (for python < 3.6)
|
||||
try:
|
||||
data = json.load(f, object_pairs_hook=collections.OrderedDict)
|
||||
except json.decoder.JSONDecodeError as err:
|
||||
print (f"Invalid json in \"{path}\": {err.msg} at line {err.lineno} (col {err.colno})")
|
||||
sys.exit(1)
|
||||
if path.endswith(".yml") or path.endswith(".yaml"):
|
||||
try:
|
||||
data = yaml_load_ordered(f)
|
||||
except yaml.YAMLError as err:
|
||||
pos = ""
|
||||
if hasattr(err, 'problem_mark'):
|
||||
mark = err.problem_mark
|
||||
pos = f" at line {mark.line+1} (col {mark.column+1})"
|
||||
print(f"Invalid yaml in \"{path}\": {err.problem}{pos}")
|
||||
sys.exit(1)
|
||||
else:
|
||||
try:
|
||||
data = json_load_ordered(f)
|
||||
except json.decoder.JSONDecodeError as err:
|
||||
print(f"Invalid json in \"{path}\": {err.msg} at line {err.lineno} (col {err.colno})")
|
||||
sys.exit(1)
|
||||
|
||||
version = int(data.get("version", "1"))
|
||||
if version == 1:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue