]> git.cworth.org Git - notmuch/blob - bindings/python-cffi/notmuch2/_config.py
Merge branch 'release'
[notmuch] / bindings / python-cffi / notmuch2 / _config.py
1 import collections.abc
2
3 import notmuch2._base as base
4 import notmuch2._capi as capi
5 import notmuch2._errors as errors
6
7
8 __all__ = ['ConfigMapping']
9
10
11 class ConfigIter(base.NotmuchIter):
12
13     def __init__(self, parent, iter_p):
14         super().__init__(
15             parent, iter_p,
16             fn_destroy=capi.lib.notmuch_config_pairs_destroy,
17             fn_valid=capi.lib.notmuch_config_pairs_valid,
18             fn_get=capi.lib.notmuch_config_pairs_key,
19             fn_next=capi.lib.notmuch_config_pairs_move_to_next)
20
21     def __next__(self):
22         # skip pairs whose value is NULL
23         while capi.lib.notmuch_config_pairs_valid(super()._iter_p):
24             val_p = capi.lib.notmuch_config_pairs_value(super()._iter_p)
25             key_p = capi.lib.notmuch_config_pairs_key(super()._iter_p)
26             if key_p == capi.ffi.NULL:
27                 # this should never happen
28                 raise errors.NullPointerError
29             key = base.BinString.from_cffi(key_p)
30             capi.lib.notmuch_config_pairs_move_to_next(super()._iter_p)
31             if val_p != capi.ffi.NULL and base.BinString.from_cffi(val_p) != "":
32                 return key
33         self._destroy()
34         raise StopIteration
35
36 class ConfigMapping(base.NotmuchObject, collections.abc.MutableMapping):
37     """The config key/value pairs loaded from the database, config file,
38     and and/or defaults.
39
40     The entries are exposed as a :class:`collections.abc.MutableMapping` object.
41     Note that setting a value to an empty string is the same as deleting it.
42
43     Mutating (deleting or updating values) in the map persists only in
44     the database, which can be shadowed by config files.
45
46     :param parent: the parent object
47     :param ptr_name: the name of the attribute on the parent which will
48        return the memory pointer.  This allows this object to
49        access the pointer via the parent's descriptor and thus
50        trigger :class:`MemoryPointer`'s memory safety.
51
52     """
53
54     def __init__(self, parent, ptr_name):
55         self._parent = parent
56         self._ptr = lambda: getattr(parent, ptr_name)
57
58     @property
59     def alive(self):
60         return self._parent.alive
61
62     def _destroy(self):
63         pass
64
65     def __getitem__(self, key):
66         if isinstance(key, str):
67             key = key.encode('utf-8')
68         val_pp = capi.ffi.new('char**')
69         ret = capi.lib.notmuch_database_get_config(self._ptr(), key, val_pp)
70         if ret != capi.lib.NOTMUCH_STATUS_SUCCESS:
71             raise errors.NotmuchError(ret)
72         val = base.BinString.from_cffi(val_pp[0])
73         capi.lib.free(val_pp[0])
74         if val == '':
75             raise KeyError
76         return val
77
78     def __setitem__(self, key, val):
79         if isinstance(key, str):
80             key = key.encode('utf-8')
81         if isinstance(val, str):
82             val = val.encode('utf-8')
83         ret = capi.lib.notmuch_database_set_config(self._ptr(), key, val)
84         if ret != capi.lib.NOTMUCH_STATUS_SUCCESS:
85             raise errors.NotmuchError(ret)
86
87     def __delitem__(self, key):
88         self[key] = ""
89
90     def __iter__(self):
91         """Return an iterator over the config items.
92
93         :raises NullPointerError: If the iterator can not be created.
94         """
95         config_pairs_p = capi.lib.notmuch_config_get_pairs(self._ptr(), b'')
96         if config_pairs_p == capi.ffi.NULL:
97             raise KeyError
98         return ConfigIter(self._parent, config_pairs_p)
99
100     def __len__(self):
101         return sum(1 for t in self)