1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
# -*- coding: UTF-8 -*-
# Copyright 2014 Red Hat, Inc.
# Part of clufter project
# Licensed under GPLv2 (a copy included | http://gnu.org/licenses/gpl-2.0.txt)
"""Command context, i.e., state distributed along filters chain"""
__author__ = "Jan Pokorný <jpokorny @at@ Red Hat .dot. com>"
from collections import MutableMapping
import logging
from .error import ClufterError
log = logging.getLogger(__name__)
class CommandContextError(ClufterError):
pass
class CommandContextBase(MutableMapping):
"""Object representing command context"""
def __init__(self, initial=None, parent=None):
if parent is None:
parent = self
self._parent = parent
try:
self._dict = dict(initial)
except TypeError:
self._dict = {}
def __delitem__(self, key):
del self._dict[key]
def __getitem__(self, key):
#return self._dict[key]
return self._dict.get(key) # make it soft-error (->setdefault reimpl.)
def setdefault(self, key, default=None):
return self._dict.setdefault(key, default)
def __iter__(self):
return iter(self._dict)
def __len__(self):
return len(self._dict)
def __setitem__(self, key, value):
self._dict[key] = CommandContextBase(initial=value, parent=self) \
if isinstance(value, dict) else value
@property
def parent(self):
return self._parent
class CommandContext(CommandContextBase):
def __init__(self, *args, **kwargs):
super(CommandContext, self).__init__(*args, **kwargs)
self._filters = {}
def _wrapping_nested_context(self, obj):
class wrapped(CommandContextBase):
def __getattribute__(self, name):
if name == 'ctxt_wrapped':
return obj
elif name == 'ctxt_set':
ret = lambda self, **kwargs: self.update(kwargs)
elif name.startswith('ctxt_'):
# by convention, ctxt_* methods are using second
# argument to pass the respective (nested) context
ret = obj.__getattribute__(name)
if callable(ret):
ret = \
lambda this, *args, **kwargs: \
ret(this, this, *args, **kwargs)
else:
try:
ret = super(wrapped, self).__getattribute__(name)
except AttributeError:
ret = obj.__getattribute__(name)
return ret
def __setattribute__(self, name, value):
obj.__setattribute__(name, value)
return (wrapped(parent=self))
def ensure_filter(self, flt):
existing, key = self._filters, flt.__class__.name
ret = existing.get(key, None)
if ret:
assert id(ret.ctxt_wrapped) == id(flt)
else:
ret = existing[key] = self._wrapping_nested_context(flt)
return ret
def ensure_filters(self, flts):
return map(self.ensure_filter, flts)
def filter(self, which):
return self._filters[which]
|