OLD | NEW |
1 # Copyright 2013-2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2013-2015 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Recipe Configuration Meta DSL. | 5 """Recipe Configuration Meta DSL. |
6 | 6 |
7 This module contains, essentially, a DSL for writing composable configurations. | 7 This module contains, essentially, a DSL for writing composable configurations. |
8 You start by defining a schema which describes how your configuration blobs will | 8 You start by defining a schema which describes how your configuration blobs will |
9 be structured, and what data they can contain. For example: | 9 be structured, and what data they can contain. For example: |
10 | 10 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 | 61 |
62 I will get back a configuraton object whose schema is FakeSchema, and whose | 62 I will get back a configuraton object whose schema is FakeSchema, and whose |
63 data is the accumulation of cool(), gnarly(), and combo(). I can continue to | 63 data is the accumulation of cool(), gnarly(), and combo(). I can continue to |
64 manipulate this configuraton object, use its data, or render it to json. | 64 manipulate this configuraton object, use its data, or render it to json. |
65 | 65 |
66 Using this system should allow you to create rich, composible, | 66 Using this system should allow you to create rich, composible, |
67 modular configurations. See the documentation on config_item_context and the | 67 modular configurations. See the documentation on config_item_context and the |
68 BaseConfig derivatives for more info. | 68 BaseConfig derivatives for more info. |
69 """ | 69 """ |
70 | 70 |
| 71 from __future__ import absolute_import |
71 import collections | 72 import collections |
72 import functools | 73 import functools |
73 import types | 74 import types |
74 | 75 |
75 from infra.libs import infra_types | |
76 | |
77 class BadConf(Exception): | 76 class BadConf(Exception): |
78 pass | 77 pass |
79 | 78 |
80 def typeAssert(obj, typearg): | 79 def typeAssert(obj, typearg): |
81 if not isinstance(obj, typearg): | 80 if not isinstance(obj, typearg): |
82 raise TypeError("Expected %r to be of type %r" % (obj, typearg)) | 81 raise TypeError("Expected %r to be of type %r" % (obj, typearg)) |
83 | 82 |
84 | 83 |
85 class ConfigContext(object): | 84 class ConfigContext(object): |
86 """A configuration context for a recipe module. | 85 """A configuration context for a recipe module. |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 obj.set_val(val) | 366 obj.set_val(val) |
368 | 367 |
369 def __delattr__(self, name): | 368 def __delattr__(self, name): |
370 obj = object.__getattribute__(self, name) | 369 obj = object.__getattribute__(self, name) |
371 typeAssert(obj, ConfigBase) | 370 typeAssert(obj, ConfigBase) |
372 obj.reset() | 371 obj.reset() |
373 | 372 |
374 def set_val(self, val): | 373 def set_val(self, val): |
375 if isinstance(val, ConfigBase): | 374 if isinstance(val, ConfigBase): |
376 val = val.as_jsonish(include_hidden=True) | 375 val = val.as_jsonish(include_hidden=True) |
377 if isinstance(val, infra_types.FrozenDict): | 376 typeAssert(val, collections.Mapping) |
378 val = infra_types.thaw(val) | |
379 typeAssert(val, dict) | |
380 | 377 |
381 val = dict(val) # because we pop later. | 378 val = dict(val) # because we pop later. |
382 for name, config_obj in self._type_map.iteritems(): | 379 for name, config_obj in self._type_map.iteritems(): |
383 if name in val: | 380 if name in val: |
384 try: | 381 try: |
385 config_obj.set_val(val.pop(name)) | 382 config_obj.set_val(val.pop(name)) |
386 except Exception as e: | 383 except Exception as e: |
387 raise Exception('While assigning key %r: %s' % (name, e)) | 384 raise Exception('While assigning key %r: %s' % (name, e)) |
388 | 385 |
389 if val: | 386 if val: |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 | 512 |
516 def __iter__(self): | 513 def __iter__(self): |
517 return iter(self.data) | 514 return iter(self.data) |
518 | 515 |
519 def __len__(self): | 516 def __len__(self): |
520 return len(self.data) | 517 return len(self.data) |
521 | 518 |
522 def set_val(self, val): | 519 def set_val(self, val): |
523 if isinstance(val, Dict): | 520 if isinstance(val, Dict): |
524 val = val.data | 521 val = val.data |
525 if isinstance(val, infra_types.FrozenDict): | 522 typeAssert(val, collections.Mapping) |
526 val = dict(val) | |
527 | |
528 typeAssert(val, dict) | |
529 for v in val.itervalues(): | 523 for v in val.itervalues(): |
530 typeAssert(v, self.value_type) | 524 typeAssert(v, self.value_type) |
531 self.data = val | 525 self.data = val |
532 | 526 |
533 def as_jsonish(self, _include_hidden=None): | 527 def as_jsonish(self, _include_hidden=None): |
534 return self.jsonish_fn(map( | 528 return self.jsonish_fn(map( |
535 self.item_fn, sorted(self.data.iteritems(), key=lambda x: x[0]))) | 529 self.item_fn, sorted(self.data.iteritems(), key=lambda x: x[0]))) |
536 | 530 |
537 def reset(self): | 531 def reset(self): |
538 self.data.clear() | 532 self.data.clear() |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 return self.data | 721 return self.data |
728 | 722 |
729 def reset(self): | 723 def reset(self): |
730 assert False | 724 assert False |
731 | 725 |
732 def complete(self): | 726 def complete(self): |
733 return True | 727 return True |
734 | 728 |
735 def _is_default(self): | 729 def _is_default(self): |
736 return True | 730 return True |
OLD | NEW |