Show More
@@ -20,13 +20,14 b' from . import (' | |||||
20 | class config(object): |
|
20 | class config(object): | |
21 | def __init__(self, data=None, includepaths=None): |
|
21 | def __init__(self, data=None, includepaths=None): | |
22 | self._data = {} |
|
22 | self._data = {} | |
23 | self._source = {} |
|
|||
24 | self._unset = [] |
|
23 | self._unset = [] | |
25 | self._includepaths = includepaths or [] |
|
24 | self._includepaths = includepaths or [] | |
26 | if data: |
|
25 | if data: | |
27 | for k in data._data: |
|
26 | for k in data._data: | |
28 | self._data[k] = data[k].copy() |
|
27 | self._data[k] = data[k].copy() | |
29 | self._source = data._source.copy() |
|
28 | self._source = data._source.copy() | |
|
29 | else: | |||
|
30 | self._source = util.cowdict() | |||
30 | def copy(self): |
|
31 | def copy(self): | |
31 | return config(self) |
|
32 | return config(self) | |
32 | def __contains__(self, section): |
|
33 | def __contains__(self, section): | |
@@ -39,13 +40,19 b' class config(object):' | |||||
39 | for d in self.sections(): |
|
40 | for d in self.sections(): | |
40 | yield d |
|
41 | yield d | |
41 | def update(self, src): |
|
42 | def update(self, src): | |
|
43 | self._source = self._source.preparewrite() | |||
42 | for s, n in src._unset: |
|
44 | for s, n in src._unset: | |
43 | if s in self and n in self._data[s]: |
|
45 | ds = self._data.get(s, None) | |
|
46 | if ds is not None and n in ds: | |||
|
47 | self._data[s] = ds.preparewrite() | |||
44 | del self._data[s][n] |
|
48 | del self._data[s][n] | |
45 | del self._source[(s, n)] |
|
49 | del self._source[(s, n)] | |
46 | for s in src: |
|
50 | for s in src: | |
47 | if s not in self: |
|
51 | ds = self._data.get(s, None) | |
48 | self._data[s] = util.sortdict() |
|
52 | if ds: | |
|
53 | self._data[s] = ds.preparewrite() | |||
|
54 | else: | |||
|
55 | self._data[s] = util.cowsortdict() | |||
49 | self._data[s].update(src._data[s]) |
|
56 | self._data[s].update(src._data[s]) | |
50 | self._source.update(src._source) |
|
57 | self._source.update(src._source) | |
51 | def get(self, section, item, default=None): |
|
58 | def get(self, section, item, default=None): | |
@@ -74,16 +81,21 b' class config(object):' | |||||
74 | assert not isinstance(value, str), ( |
|
81 | assert not isinstance(value, str), ( | |
75 | 'config values may not be unicode strings on Python 3') |
|
82 | 'config values may not be unicode strings on Python 3') | |
76 | if section not in self: |
|
83 | if section not in self: | |
77 | self._data[section] = util.sortdict() |
|
84 | self._data[section] = util.cowsortdict() | |
|
85 | else: | |||
|
86 | self._data[section] = self._data[section].preparewrite() | |||
78 | self._data[section][item] = value |
|
87 | self._data[section][item] = value | |
79 | if source: |
|
88 | if source: | |
|
89 | self._source = self._source.preparewrite() | |||
80 | self._source[(section, item)] = source |
|
90 | self._source[(section, item)] = source | |
81 |
|
91 | |||
82 | def restore(self, data): |
|
92 | def restore(self, data): | |
83 | """restore data returned by self.backup""" |
|
93 | """restore data returned by self.backup""" | |
|
94 | self._source = self._source.preparewrite() | |||
84 | if len(data) == 4: |
|
95 | if len(data) == 4: | |
85 | # restore old data |
|
96 | # restore old data | |
86 | section, item, value, source = data |
|
97 | section, item, value, source = data | |
|
98 | self._data[section] = self._data[section].preparewrite() | |||
87 | self._data[section][item] = value |
|
99 | self._data[section][item] = value | |
88 | self._source[(section, item)] = source |
|
100 | self._source[(section, item)] = source | |
89 | else: |
|
101 | else: | |
@@ -149,7 +161,7 b' class config(object):' | |||||
149 | if remap: |
|
161 | if remap: | |
150 | section = remap.get(section, section) |
|
162 | section = remap.get(section, section) | |
151 | if section not in self: |
|
163 | if section not in self: | |
152 | self._data[section] = util.sortdict() |
|
164 | self._data[section] = util.cowsortdict() | |
153 | continue |
|
165 | continue | |
154 | m = itemre.match(l) |
|
166 | m = itemre.match(l) | |
155 | if m: |
|
167 | if m: |
@@ -588,6 +588,24 b' def cachefunc(func):' | |||||
588 |
|
588 | |||
589 | return f |
|
589 | return f | |
590 |
|
590 | |||
|
591 | class cow(object): | |||
|
592 | """helper class to make copy-on-write easier | |||
|
593 | ||||
|
594 | Call preparewrite before doing any writes. | |||
|
595 | """ | |||
|
596 | ||||
|
597 | def preparewrite(self): | |||
|
598 | """call this before writes, return self or a copied new object""" | |||
|
599 | if getattr(self, '_copied', 0): | |||
|
600 | self._copied -= 1 | |||
|
601 | return self.__class__(self) | |||
|
602 | return self | |||
|
603 | ||||
|
604 | def copy(self): | |||
|
605 | """always do a cheap copy""" | |||
|
606 | self._copied = getattr(self, '_copied', 0) + 1 | |||
|
607 | return self | |||
|
608 | ||||
591 | class sortdict(collections.OrderedDict): |
|
609 | class sortdict(collections.OrderedDict): | |
592 | '''a simple sorted dictionary |
|
610 | '''a simple sorted dictionary | |
593 |
|
611 | |||
@@ -613,6 +631,38 b' class sortdict(collections.OrderedDict):' | |||||
613 | for k, v in src: |
|
631 | for k, v in src: | |
614 | self[k] = v |
|
632 | self[k] = v | |
615 |
|
633 | |||
|
634 | class cowdict(cow, dict): | |||
|
635 | """copy-on-write dict | |||
|
636 | ||||
|
637 | Be sure to call d = d.preparewrite() before writing to d. | |||
|
638 | ||||
|
639 | >>> a = cowdict() | |||
|
640 | >>> a is a.preparewrite() | |||
|
641 | True | |||
|
642 | >>> b = a.copy() | |||
|
643 | >>> b is a | |||
|
644 | True | |||
|
645 | >>> c = b.copy() | |||
|
646 | >>> c is a | |||
|
647 | True | |||
|
648 | >>> a = a.preparewrite() | |||
|
649 | >>> b is a | |||
|
650 | False | |||
|
651 | >>> a is a.preparewrite() | |||
|
652 | True | |||
|
653 | >>> c = c.preparewrite() | |||
|
654 | >>> b is c | |||
|
655 | False | |||
|
656 | >>> b is b.preparewrite() | |||
|
657 | True | |||
|
658 | """ | |||
|
659 | ||||
|
660 | class cowsortdict(cow, sortdict): | |||
|
661 | """copy-on-write sortdict | |||
|
662 | ||||
|
663 | Be sure to call d = d.preparewrite() before writing to d. | |||
|
664 | """ | |||
|
665 | ||||
616 | class transactional(object): |
|
666 | class transactional(object): | |
617 | """Base class for making a transactional type into a context manager.""" |
|
667 | """Base class for making a transactional type into a context manager.""" | |
618 | __metaclass__ = abc.ABCMeta |
|
668 | __metaclass__ = abc.ABCMeta |
General Comments 0
You need to be logged in to leave comments.
Login now