From c4c0f87384c861541223be07b0f9d62447c3cfa6 Mon Sep 17 00:00:00 2001 From: Petr Šabata Date: May 05 2017 09:43:48 +0000 Subject: Provide interface for manipulating multidocuments This commit adds load_all(), loads_all(), dump_all() and dumps_all() modulemd functions to load and dump modulemd multidocuments. Signed-off-by: Petr Šabata --- diff --git a/modulemd/__init__.py b/modulemd/__init__.py index 0e30efe..2155ed7 100644 --- a/modulemd/__init__.py +++ b/modulemd/__init__.py @@ -58,6 +58,46 @@ from modulemd.profile import ModuleProfile supported_mdversions = ( 1, ) +def load_all(f): + """Loads a metadata file containing multiple modulemd documents + into a list of ModuleMetadata instances. + + :param str f: File name to load + """ + with open(f, "r") as infile: + data = infile.read() + return loads_all(data) + +def loads_all(s): + """Loads multiple modulemd documents from a YAML multidocument + string. + + :param str s: String containing multiple YAML documents. + """ + l = list() + for doc in yaml.load_all(s): + m = ModuleMetadata() + m.loadd(doc) + l.append(m) + return l + +def dump_all(f, l): + """Dumps a list of ModuleMetadata instances into a file. + + :param str f: Output filename + :param list l: List of ModuleMetadata instances + """ + with open(f, "w") as outfile: + outfile.write(dumps_all(l)) + +def dumps_all(l): + """Dumps a list of ModuleMetadata instance into a YAML multidocument + string. + + :param list l: List of ModuleMetadata instances + """ + return yaml.dump_all([x.dumpd() for x in l], explicit_start=True) + class ModuleMetadata(object): """Class representing the whole module.""" @@ -141,9 +181,17 @@ class ModuleMetadata(object): """Loads metadata from a string. :param str s: Raw metadata in YAML + """ + yamld = yaml.safe_load(s) + self.loadd(yamld) + + def loadd(self, d): + """Loads metadata from a dictionary. + + :param dict d: YAML metadata parsed into a dict :raises ValueError: If the metadata is invalid or unsupported. """ - yml = yaml.safe_load(s) + yml = d if "document" not in yml or yml["document"] != "modulemd": raise ValueError("The supplied data isn't a valid modulemd document") if "version" not in yml: @@ -271,10 +319,10 @@ class ModuleMetadata(object): with open(f, "w") as outfile: outfile.write(data) - def dumps(self): - """Dumps te metadata into a string. + def dumpd(self): + """Dumps the metadata into a dictionary. - :rtype: str + :rtype: dict """ data = dict() # header @@ -371,7 +419,14 @@ class ModuleMetadata(object): data["data"]["artifacts"] = dict() if self.artifacts.rpms: data["data"]["artifacts"]["rpms"] = list(self.artifacts.rpms) - return yaml.safe_dump(data) + return data + + def dumps(self): + """Dumps the metadata into a string. + + :rtype: str + """ + return yaml.safe_dump(self.dumpd()) @property def mdversion(self): diff --git a/modulemd/tests/test_io.py b/modulemd/tests/test_io.py index c44eec0..a90544d 100644 --- a/modulemd/tests/test_io.py +++ b/modulemd/tests/test_io.py @@ -32,7 +32,7 @@ import sys DIR = os.path.dirname(__file__) sys.path.insert(0, os.path.join(DIR, "..")) -from modulemd import ModuleMetadata +from modulemd import ModuleMetadata, dump_all, load_all class TestIO(unittest.TestCase): maxDiff = None # display diff when a test fails @@ -132,3 +132,16 @@ class TestIO(unittest.TestCase): # http://stackoverflow.com/questions/5121931/in-python-how-can-you-load-yaml-mappings-as-ordereddicts self.assertEqual(first, second) os.remove("testdump.yaml") + + def test_reload_all(self): + a = ModuleMetadata() + b = ModuleMetadata() + a.name = 'a' + b.name = 'b' + arepr = repr(a) + brepr = repr(b) + dump_all("testdumpall.yaml", [a, b]) + a, b = load_all("testdumpall.yaml") + self.assertEqual(arepr, repr(a)) + self.assertEqual(brepr, repr(b)) + os.remove("testdumpall.yaml")