/
context.py
116 lines (99 loc) · 3.88 KB
/
context.py
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import os
import pkg_resources
import re
from repoze.configuration.exceptions import ConfigurationConflict
from repoze.configuration.loader import YAMLPluginLoader
_INTERP = re.compile(r"%\(([^)]*)\)s")
class Context(object):
def __init__(self, registry, loader=None):
if loader is None:
loader = YAMLPluginLoader
self.loader = loader
self.registry = registry
self.actions = []
self.stack = []
self.discriminators = {}
def interpolate(self, value):
def _interpolation_replace(match):
s = match.group(1)
if s in self.registry:
return self.registry[s]
if self.stack and s in self.stack[-1]:
return self.stack[-1][s]
raise KeyError(s)
if '%(' in value:
value = _INTERP.sub(_interpolation_replace, value)
return value.encode('utf-8')
def action(self, declaration, callback, discriminator=None, override=False):
stack_override = self.stack and self.stack[-1]['override']
effective_override = override or stack_override
if not effective_override:
if discriminator in self.discriminators:
conflicting_action = self.discriminators[discriminator]
raise ConfigurationConflict(declaration,
conflicting_action.declaration)
action = Action(discriminator, callback, declaration)
self.actions.append(action)
self.discriminators[discriminator] = action
def resolve(self, dottedname):
if dottedname.startswith('.') or dottedname.startswith(':'):
package = self.current_package()
if not package:
raise ImportError('name "%s" is irresolveable (no package)' %
dottedname)
if dottedname in ['.', ':']:
dottedname = package.__name__
else:
dottedname = package.__name__ + dottedname
return pkg_resources.EntryPoint.parse(
'x=%s' % dottedname).load(False)
def current_package(self):
if not self.stack:
return None
return self.stack[-1]['package']
def current_override(self):
if not self.stack:
return False
return self.stack[-1]['override']
def stream(self, filename, package=None):
if os.path.isabs(filename):
return open(filename)
if package is None:
package = self.current_package()
if package is None:
return open(filename)
else:
return pkg_resources.resource_stream(package.__name__, filename)
def abs_filename(self, filename, package=None):
if os.path.isabs(filename):
return filename
if package is None:
package = self.current_package()
if package is None:
return os.path.abspath(filename)
else:
return pkg_resources.resource_filename(package.__name__, filename)
def load(self, filename, package, override=False, loader=None):
fn = self.abs_filename(filename, package)
here = os.path.dirname(fn)
stream = self.stream(filename, package)
self.stack.append({'filename':filename, 'package':package,
'override':override, 'here':here})
if loader is None:
loader = self.loader
try:
loader(self, stream)
finally:
self.stack.pop()
def execute(self):
for action in self.actions:
action.execute()
return self.registry
class Action(object):
def __init__(self, discriminator, callback, declaration):
self.discriminator = discriminator
self.callback = callback
self.declaration = declaration
def execute(self):
if self.callback is not None:
self.callback()