class Emitter: def __init__(self, accessor, item_map): self.raw_accessor = Accessor() self.accessor = accessor self.item_map = item_map @reify def ref_walking(self): return DictWalker([is_ref]) def get_item_by_globalref(self, globalref): return self.accessor.cache[globalref] def get_item_by_localref(self, localref): return self.item_map[localref] def emit(self, resolver, doc, *, conflicted): # side effect d = make_dict() for path, sd in self.ref_walking.iterate(doc): self.replace_ref(resolver, sd) d = deepmerge(d, doc) for name, item in self.item_map.items(): if name == "": continue data = item.data # replace: <file.yaml>#/<ref> -> #/<ref> for path, sd in self.ref_walking.iterate(data): if not sd["$ref"].startswith("#/"): self.replace_ref(item.resolver, sd) if sd["$ref"] in conflicted: self.replace_ref(item.resolver, sd) self.raw_accessor.assign(d, name.split("/"), data) # adhoc paths support will_removes = set() paths = d.get("paths") or {} for path, sub in list(paths.items()): if "$ref" in sub and sub["$ref"].startswith("#/"): related_path = tuple(sub["$ref"][2:].split("/")) paths[path] = self.raw_accessor.access(d, related_path).copy() will_removes.add(related_path) for related_path in will_removes: self.raw_accessor.maybe_remove(d, related_path) return d def replace_ref(self, resolver, sd): filename, _, pointer = resolver.resolve_pathset(sd["$ref"]) related = self.get_item_by_globalref((filename, pointer)) new_ref = "#/{}".format(related.localref) if sd["$ref"] != new_ref: logger.debug( "fix ref: %r -> %r (where=%r)", sd["$ref"], new_ref, resolver.filename ) sd["$ref"] = new_ref
print(['a', 'b', 'c'], a.access(d, ['a', 'b', 'c'])) # print(['a', 'b', 'x'], a.access(d, ['a', 'b', 'x'])) # error # exists with indent(2, '\nexists:\n'): import copy # NOQA d2 = copy.deepcopy(d) print(['a', 'b', 'c'], a.exists(d2, ['a', 'b', 'c'])) print(['a', 'b', 'x'], a.exists(d2, ['a', 'b', 'x'])) # maybe_remove with indent(2, '\nmaybe_remove:\n'): import copy # NOQA d2 = copy.deepcopy(d) print(['a', 'b', 'x'], a.maybe_remove(d2, ['a', 'b', 'x'])) print(['a', 'b', 'c'], a.maybe_remove(d2, ['a', 'b', 'c'])) pp(d2) print() # maybe_access_container (this is not good name!!) with indent(2, '\nmaybe_access_container:\n'): print(['a', 'b', 'x'], a.maybe_access_container(d, ['a', 'b', 'x'])) print(['a', 'b', 'c'], a.maybe_access_container(d, ['a', 'b', 'c'])) # maybe_access (this is not good name!!) with indent(2, '\nmaybe_access:\n'): print(['a', 'b', 'x'], a.maybe_access(d, ['a', 'b', 'x'])) print(['a', 'b', 'c'], a.maybe_access(d, ['a', 'b', 'c']))