|  | # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | # Use of this source code is governed by a BSD-style license that can be | 
|  | # found in the LICENSE file. | 
|  |  | 
|  | import copy | 
|  |  | 
|  | import json_parse | 
|  |  | 
|  |  | 
|  | def DeleteNodes(item, delete_key=None, matcher=None): | 
|  | """Deletes certain nodes in item, recursively. If |delete_key| is set, all | 
|  | dicts with |delete_key| as an attribute are deleted. If a callback is passed | 
|  | as |matcher|, |DeleteNodes| will delete all dicts for which matcher(dict) | 
|  | returns True. | 
|  | """ | 
|  | assert (delete_key is not None) != (matcher is not None) | 
|  |  | 
|  | def ShouldDelete(thing): | 
|  | return json_parse.IsDict(thing) and ( | 
|  | delete_key is not None and delete_key in thing or | 
|  | matcher is not None and matcher(thing)) | 
|  |  | 
|  | if json_parse.IsDict(item): | 
|  | toDelete = [] | 
|  | for key, value in item.items(): | 
|  | if ShouldDelete(value): | 
|  | toDelete.append(key) | 
|  | else: | 
|  | DeleteNodes(value, delete_key, matcher) | 
|  | for key in toDelete: | 
|  | del item[key] | 
|  | elif type(item) == list: | 
|  | item[:] = [DeleteNodes(thing, delete_key, matcher) | 
|  | for thing in item if not ShouldDelete(thing)] | 
|  |  | 
|  | return item | 
|  |  | 
|  |  | 
|  | def Load(filename): | 
|  | with open(filename, 'r') as handle: | 
|  | schemas = json_parse.Parse(handle.read()) | 
|  | return schemas | 
|  |  | 
|  |  | 
|  | # A dictionary mapping |filename| to the object resulting from loading the JSON | 
|  | # at |filename|. | 
|  | _cache = {} | 
|  |  | 
|  |  | 
|  | def CachedLoad(filename): | 
|  | """Equivalent to Load(filename), but caches results for subsequent calls""" | 
|  | if filename not in _cache: | 
|  | _cache[filename] = Load(filename) | 
|  | # Return a copy of the object so that any changes a caller makes won't affect | 
|  | # the next caller. | 
|  | return copy.deepcopy(_cache[filename]) | 
|  |  |