Sapan Bhatia | bcbe8ce | 2017-11-14 13:02:30 -0500 | [diff] [blame] | 1 | # Copyright 2017-present Open Networking Foundation |
| 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 | from mock import Mock |
| 16 | import random |
| 17 | |
| 18 | def mock_enumerator(items): |
| 19 | e = lambda:None |
| 20 | e.all = lambda:items |
| 21 | return e |
| 22 | |
Scott Baker | d1702d7 | 2017-11-17 12:12:00 -0800 | [diff] [blame] | 23 | # A list of all mock object stores that have been created |
| 24 | AllMockObjectStores = [] |
| 25 | |
| 26 | class MockObjectList: |
| 27 | item_list = None |
| 28 | |
| 29 | def __init__(self, initial=None): |
| 30 | self.id_counter = 0 |
| 31 | if initial: |
| 32 | self.item_list=initial |
| 33 | elif self.item_list is None: |
| 34 | self.item_list=[] |
| 35 | |
| 36 | def get_items(self): |
| 37 | return self.item_list |
| 38 | |
| 39 | def count(self): |
| 40 | return len(self.get_items()) |
| 41 | |
| 42 | def first(self): |
| 43 | return self.get_items()[0] |
| 44 | |
| 45 | def all(self): |
| 46 | return self.get_items() |
| 47 | |
| 48 | def filter(self, **kwargs): |
| 49 | items = self.get_items() |
| 50 | for (k,v) in kwargs.items(): |
| 51 | items = [x for x in items if getattr(x,k) == v] |
| 52 | return items |
| 53 | |
| 54 | def get(self, **kwargs): |
| 55 | objs = self.filter(**kwargs) |
| 56 | if not objs: |
Matteo Scandolo | aee7e45 | 2018-05-21 16:45:35 -0700 | [diff] [blame] | 57 | raise IndexError("No objects matching %s" % str(kwargs)) |
Scott Baker | d1702d7 | 2017-11-17 12:12:00 -0800 | [diff] [blame] | 58 | return objs[0] |
| 59 | |
| 60 | class MockObjectStore(MockObjectList): |
| 61 | def save(self, o): |
| 62 | if (not hasattr(o,"id")) or (not o.id) or (o.id==98052): |
| 63 | for item in self.get_items(): |
| 64 | if item.id >= self.id_counter: |
| 65 | self.id_counter = item.id + 1 |
| 66 | |
| 67 | o.id = self.id_counter |
| 68 | self.id_counter = self.id_counter + 1 |
| 69 | |
| 70 | for item in self.get_items(): |
| 71 | if item.id == o.id: |
| 72 | item = o |
| 73 | break |
| 74 | else: |
| 75 | self.get_items().append(o) |
| 76 | |
Scott Baker | 5b7fba0 | 2018-10-17 08:46:46 -0700 | [diff] [blame] | 77 | class MockObject(object): |
Scott Baker | d1702d7 | 2017-11-17 12:12:00 -0800 | [diff] [blame] | 78 | objects = None |
| 79 | id = None |
| 80 | deleted = False |
| 81 | |
Scott Baker | 5b7fba0 | 2018-10-17 08:46:46 -0700 | [diff] [blame] | 82 | field_names = [] |
| 83 | |
Sapan Bhatia | bcbe8ce | 2017-11-14 13:02:30 -0500 | [diff] [blame] | 84 | def __init__(self, **kwargs): |
Scott Baker | 5b7fba0 | 2018-10-17 08:46:46 -0700 | [diff] [blame] | 85 | object.__setattr__(self, 'is_set', {}) |
| 86 | |
Sapan Bhatia | bcbe8ce | 2017-11-14 13:02:30 -0500 | [diff] [blame] | 87 | setattr(self, 'backend_code', 0) |
| 88 | setattr(self, 'id', 98052) |
| 89 | setattr(self, 'pk', random.randint(0, 1<<30)) |
Scott Baker | 5b7fba0 | 2018-10-17 08:46:46 -0700 | [diff] [blame] | 90 | |
| 91 | self.leaf_model = self |
| 92 | |
| 93 | # reset is_set |
| 94 | self.is_set = {} |
| 95 | |
Sapan Bhatia | bcbe8ce | 2017-11-14 13:02:30 -0500 | [diff] [blame] | 96 | for (k,v) in kwargs.items(): |
| 97 | setattr(self,k,v) |
| 98 | |
Scott Baker | 5b7fba0 | 2018-10-17 08:46:46 -0700 | [diff] [blame] | 99 | self.is_new = True |
| 100 | self._initial = self._dict |
| 101 | |
| 102 | def __setattr__(self, name, value): |
| 103 | self.is_set[name] = True |
| 104 | object.__setattr__(self, name, value) |
| 105 | |
Scott Baker | d1702d7 | 2017-11-17 12:12:00 -0800 | [diff] [blame] | 106 | @property |
| 107 | def self_content_type_id(self): |
| 108 | return self.__class__.__name__ |
| 109 | |
Scott Baker | e049955 | 2018-05-18 12:07:53 -0700 | [diff] [blame] | 110 | def save(self, update_fields=[], always_update_timestamp=False): |
Scott Baker | d1702d7 | 2017-11-17 12:12:00 -0800 | [diff] [blame] | 111 | if self.objects: |
| 112 | self.objects.save(self) |
| 113 | |
| 114 | def delete(self): |
| 115 | pass |
Sapan Bhatia | bcbe8ce | 2017-11-14 13:02:30 -0500 | [diff] [blame] | 116 | |
| 117 | def tologdict(self): |
| 118 | return {} |
| 119 | |
Scott Baker | 5b7fba0 | 2018-10-17 08:46:46 -0700 | [diff] [blame] | 120 | @property |
| 121 | def _dict(self): |
| 122 | d={} |
| 123 | for name in self.field_names: |
| 124 | if self.is_set.get(name, False): |
| 125 | d[name] = getattr(self, name) |
| 126 | return d |
| 127 | |
| 128 | @property |
| 129 | def diff(self): |
| 130 | d1 = self._initial |
| 131 | d2 = self._dict |
| 132 | all_field_names = self.field_names |
| 133 | diffs=[] |
| 134 | for k in all_field_names: |
| 135 | if (d1.get(k,None) != d2.get(k,None)): |
| 136 | diffs.append( (k, (d1.get(k,None), d2.get(k,None))) ) |
| 137 | |
| 138 | return dict(diffs) |
| 139 | |
| 140 | @property |
| 141 | def has_changed(self): |
| 142 | return bool(self.diff) |
| 143 | |
| 144 | @property |
| 145 | def changed_fields(self): |
| 146 | if self.is_new: |
| 147 | return self._dict.keys() |
| 148 | return self.diff.keys() |
| 149 | |
| 150 | def has_field_changed(self, field_name): |
| 151 | return field_name in self.diff.keys() |
| 152 | |
| 153 | def get_field_diff(self, field_name): |
| 154 | return self.diff.get(field_name, None) |
| 155 | |
| 156 | def recompute_initial(self): |
| 157 | self._initial = self._dict |
| 158 | |
| 159 | def save_changed_fields(self, always_update_timestamp=False): |
| 160 | if self.has_changed: |
| 161 | update_fields = self.changed_fields |
| 162 | if always_update_timestamp and "updated" not in update_fields: |
| 163 | update_fields.append("updated") |
| 164 | self.save(update_fields=sorted(update_fields), always_update_timestamp=always_update_timestamp) |
| 165 | |
| 166 | |
Scott Baker | d1702d7 | 2017-11-17 12:12:00 -0800 | [diff] [blame] | 167 | def get_MockObjectStore(x): |
| 168 | store = globals()["Mock%sObjects" % x]() |
| 169 | if not store in AllMockObjectStores: |
| 170 | AllMockObjectStores.append(store) |
| 171 | return store |
Sapan Bhatia | bcbe8ce | 2017-11-14 13:02:30 -0500 | [diff] [blame] | 172 | |
Scott Baker | c2fddaa | 2019-01-30 15:45:03 -0800 | [diff] [blame] | 173 | class ModelAccessor(object): |
| 174 | def check_db_connection_okay(self): |
Sapan Bhatia | bcbe8ce | 2017-11-14 13:02:30 -0500 | [diff] [blame] | 175 | return True |
| 176 | |
Scott Baker | c2fddaa | 2019-01-30 15:45:03 -0800 | [diff] [blame] | 177 | def connection_close(self): |
| 178 | pass |
| 179 | |
| 180 | def journal_object(self, *args, **kwargs): |
| 181 | pass |
| 182 | |
| 183 | def obj_exists(self, o): |
| 184 | # gRPC will default id to '0' for uninitialized objects |
| 185 | return (o.id is not None) and (o.id != 0) |
| 186 | |
Sapan Bhatia | bcbe8ce | 2017-11-14 13:02:30 -0500 | [diff] [blame] | 187 | def fetch_pending(self, model, deleted = False): |
| 188 | num = random.randint(1, 5) |
| 189 | object_list = [] |
| 190 | |
| 191 | for i in range(num): |
| 192 | if isinstance(model, list): |
| 193 | model = model[0] |
| 194 | |
| 195 | try: |
| 196 | obj = model() |
| 197 | except: |
| 198 | import pdb |
| 199 | pdb.set_trace() |
| 200 | |
| 201 | obj.name = "Opinionated Berry %d"%i |
| 202 | object_list.append(obj) |
| 203 | |
| 204 | return object_list |
| 205 | |
Scott Baker | d1702d7 | 2017-11-17 12:12:00 -0800 | [diff] [blame] | 206 | def reset_all_object_stores(self): |
| 207 | for store in AllMockObjectStores: |
| 208 | store.items = [] |
| 209 | |
Matteo Scandolo | a6a25c4 | 2018-03-13 16:04:22 -0700 | [diff] [blame] | 210 | def get_model_class(self, classname): |
| 211 | return globals()[classname] |
| 212 | |
Scott Baker | c2fddaa | 2019-01-30 15:45:03 -0800 | [diff] [blame] | 213 | def has_model_class(self, classname): |
| 214 | return classname in globals() |
| 215 | |
| 216 | def __getattr__(self, name): |
| 217 | """ Wrapper for getattr to facilitate retrieval of classes """ |
| 218 | has_model_class = self.__getattribute__("has_model_class") |
| 219 | get_model_class = self.__getattribute__("get_model_class") |
| 220 | if has_model_class(name): |
| 221 | return get_model_class(name) |
| 222 | |
| 223 | # Default behaviour |
| 224 | return self.__getattribute__(name) |
| 225 | |
Sapan Bhatia | bcbe8ce | 2017-11-14 13:02:30 -0500 | [diff] [blame] | 226 | model_accessor = ModelAccessor() |
| 227 | |
Scott Baker | 4839dec | 2019-02-27 16:50:37 -0800 | [diff] [blame] | 228 | def get_first_site(): |
| 229 | return model_accessor.Site.objects.first().id |
| 230 | |
Sapan Bhatia | bcbe8ce | 2017-11-14 13:02:30 -0500 | [diff] [blame] | 231 | class ObjectSet(object): |
| 232 | def __init__(self, objects): |
| 233 | self.objects = objects |
| 234 | |
| 235 | def all(self): |
| 236 | return self.objects |
| 237 | |
| 238 | ##### |
| 239 | # DO NOT MODIFY THE CLASSES BELOW. THEY ARE AUTOGENERATED. |
| 240 | # |
| 241 | |
| 242 | {% for m in proto.messages -%} |
Scott Baker | d1702d7 | 2017-11-17 12:12:00 -0800 | [diff] [blame] | 243 | class Mock{{ m.name }}Objects(MockObjectStore): pass |
| 244 | class {{ m.name }}(MockObject): |
| 245 | objects = get_MockObjectStore("{{ m.name }}") |
Sapan Bhatia | bcbe8ce | 2017-11-14 13:02:30 -0500 | [diff] [blame] | 246 | {% for f in xproto_base_fields(m, proto.message_table) + m.fields -%} |
| 247 | {{ f.name }} = {{ xproto_first_non_empty([f.options.default, "None"]) }} |
Scott Baker | d1702d7 | 2017-11-17 12:12:00 -0800 | [diff] [blame] | 248 | {% if f.link -%}{{ f.name }}_id = None{% endif %} |
Sapan Bhatia | bcbe8ce | 2017-11-14 13:02:30 -0500 | [diff] [blame] | 249 | {% endfor %} |
| 250 | leaf_model_name = "{{ m.name }}" |
Scott Baker | 5b7fba0 | 2018-10-17 08:46:46 -0700 | [diff] [blame] | 251 | |
| 252 | field_names = ["id", \ |
| 253 | {% for f in xproto_base_fields(m, proto.message_table) + m.fields -%} |
| 254 | "{{ f.name }}", |
| 255 | {% endfor %} |
| 256 | ] |
| 257 | |
Sapan Bhatia | bcbe8ce | 2017-11-14 13:02:30 -0500 | [diff] [blame] | 258 | {% endfor %} |