1# Copyright 2016 - Google, Inc. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15 16class DataWrapper(object): 17 """A special type of packed data. 18 19 This is the base class for a type of data that wraps around another set 20 of data. This data will be unpacked on every read right before the real 21 value is needed. When unpacked the wrapper can perform special operations 22 to get the real data. 23 """ 24 25 def get_real_value(self, unwrapper): 26 """Unpacks the data from the wrapper. 27 28 Args: 29 unwrapper: The object calling the unwrapping. 30 31 Returns: 32 The real value stored in the data wrapper. 33 """ 34 value = self.unwrap(unwrapper) 35 while isinstance(value, DataWrapper): 36 value = value.unwrap(unwrapper) 37 38 return value 39 40 def unwrap(self, unwrapper): 41 """Unwraps the data from this wrapper and this wrapper only. 42 43 Unlike get_real_value, this method is abstract and is where user 44 code can be written to unpack the data value. If this returns 45 another data wrapper then get_real_value will continue to unwrap 46 until a true value is given. 47 48 Args: 49 unwrapper: The object calling the unwrapping. 50 51 Returns: 52 The unwrapped data. 53 """ 54 pass 55 56 57class ConfigWrapper(object): 58 """Object used to asses config values. 59 60 Base class for all objects that wrap around the configs loaded into the 61 application. 62 """ 63 64 def get_value(self, key): 65 """Reads the value of a config at a certain key. 66 67 Args: 68 key: The key of the value to read. 69 70 Returns: 71 The raw value stored at that key. 72 """ 73 raise NotImplementedError() 74 75 def set_value(self, key, value): 76 """Writes a new value into the config at a certain key. 77 78 Args: 79 key: The key to write the value at. 80 value: The new value to store at that key. 81 """ 82 raise NotImplementedError() 83 84 def has_value(self, key): 85 """Checks if this config has a certain key. 86 87 Args: 88 key: The key to check for. 89 90 Returns: 91 True if the key exists. 92 """ 93 raise NotImplementedError() 94 95 def keys(self): 96 """Gets all keys in this config. 97 98 Returns: 99 An iterator (or some iterable object) with all keys in this config. 100 """ 101 raise NotImplementedError() 102 103 def __getitem__(self, key): 104 """Overrides the bracket accessor to read a value. 105 106 Unlike get_value, this will return the true value of a config. This 107 will unpack any data wrappers. 108 109 Args: 110 key: The key to read. 111 112 Returns: 113 The true value stored at the key. 114 """ 115 value = self.get_value(key) 116 if isinstance(value, DataWrapper): 117 return value.get_real_value(self) 118 else: 119 return value 120 121 def __setitem__(self, key, value): 122 """Overrides the bracket accessor to write a value. 123 124 Args: 125 key: The key to write to. 126 """ 127 return self.set_value(key, value) 128 129 def __iter__(self): 130 """Iterates over all values in the config. 131 132 Returns: 133 An iterator of key, value pairs. 134 """ 135 for key in self.keys(): 136 yield (key, self[key]) 137