ValueError: replaces() must be used only once per class; there is already a |
ValueError: replaces() must be used only once per class; there is already a |
value for ``get``: <bound method ...get of <class 'S1'>> |
value for ``get``: <bound method ...get of <class 'S1'>> |
|
|
|
Services should be subclassable and super() should be usable in spite of all |
|
the singleton-izing magic, for both instance and class methods:: |
|
|
|
>>> class Base(context.Service): |
|
... def test(self, other=None): |
|
... print "hello from Base" |
|
... if other is not None and other is not self: |
|
... print "insanity!" |
|
... t2 = classmethod(test) |
|
|
|
>>> class Sub(Base): |
|
... def test(self): |
|
... print "hello from sub" |
|
... super(Sub, self).test(self) |
|
... def t2(cls): |
|
... print "hello from sub cm" |
|
... super(Sub, cls).t2() |
|
... t2 = classmethod(t2) |
|
|
|
>>> Base.get() is Sub.get() |
|
False |
|
|
|
>>> Sub.test() |
|
hello from sub |
|
hello from Base |
|
|
|
>>> Sub.t2() |
|
hello from sub cm |
|
hello from Base |
|
|
|
Service attributes should be settable and deletable, mapped to the instance:: |
|
|
|
>>> class Dummy(context.Service): |
|
... foo = 42 |
|
|
|
>>> Dummy.foo |
|
42 |
|
|
|
>>> Dummy.foo = 99 |
|
>>> Dummy().foo |
|
42 |
|
|
|
>>> Dummy.get().foo |
|
99 |
|
|
|
>>> del Dummy.foo |
|
>>> Dummy.foo |
|
42 |
|
>>> Dummy.get().foo |
|
42 |
|
|
|
|
Configuration Objects |
Configuration Objects |
>>> c2[1] = 3 |
>>> c2[1] = 3 |
Traceback (most recent call last): |
Traceback (most recent call last): |
... |
... |
SettingConflict: a different value for 1 is already defined |
SettingConflict: (1, 2, 3) |
|
|
>>> c3[1] = 9 |
>>> c3[1] = 9 |
>>> c3[1] |
>>> c3[1] |
|
|
>>> c.__exit__(None, None, None) |
>>> c.__exit__(None, None, None) |
|
|
>>> c3[aSetting] = 99 |
>>> c3[aSetting] = 42 |
|
>>> c3[aSetting] = 99 # multiple writes okay as long as not read yet |
>>> c3[aSetting] |
>>> c3[aSetting] |
99 |
99 |
>>> c3[aSetting] = 99 |
>>> c3[aSetting] = 99 |
Applications and Services |
Applications and Services |
========================= |
========================= |
|
|
|
Simple service replacement in a new application context:: |
|
|
|
>>> S1.get() |
|
<S1 object ...> |
|
|
|
>>> app = context.App() |
|
>>> app[S1] = S2 |
|
|
|
>>> old = app.swap() |
|
|
|
>>> S1.get() |
|
<S2 object ...> |
|
|
|
>>> app is old.swap() |
|
True |
|
|
|
|
By default, service factories are always executed in the context of the |
By default, service factories are always executed in the context of the |
application's main configuration, even if a different configuration is active |
application's main configuration, even if a different configuration is active |
at the time the service is requested:: |
at the time the service is requested:: |
|
|
>>> a = context.App(context.Config()) |
>>> a1 = context.App() |
|
|
>>> def factory(): |
>>> def factory(): |
... print aSetting() |
... print aSetting() |
... return S2() |
... return S2() |
>>> a.config[S1] = factory |
>>> a1[S1] = factory |
>>> context.with_(a.swap(), lambda a: S1.get()) |
>>> a1[S1] is factory |
|
True |
|
|
|
>>> old = a1.swap() |
|
>>> context.App[S1] is factory |
|
True |
|
|
|
>>> S1.get() |
42 |
42 |
<S2 object ...> |
<S2 object ...> |
|
|
>>> a = context.App(context.Config()) |
>>> a2 = context.App() |
>>> a.config[S1] = factory |
>>> a2[S1] = factory |
>>> c = context.Config(a.config) |
>>> c = context.Config(a2.config) |
>>> c[aSetting] = 999 |
>>> c[aSetting] = 999 |
>>> context.with_(a.swap(), lambda a: context.with_(c, lambda c: S1.get())) |
>>> context.with_(context.switch_to(a2), lambda a: context.with_(c, lambda c: S1.get())) |
42 |
42 |
<S2 object ...> |
<S2 object ...> |
|
|
|
>>> context.App.get() is a1 # verify switch_to() manager restored a1 |
|
True |
|
|
|
>>> a1 is old.swap() # verify swap returns previous value |
|
True |
|
|
|
>>> context.App.get() is old # verify swap sets target |
|
True |
|
|
|
|
|
|
Namespaces |
Namespaces |
>>> act.__exit__(None,None,None) # no __exit__ for failed __enter__ |
>>> act.__exit__(None,None,None) # no __exit__ for failed __enter__ |
|
|
|
|
|
Source Lines |
|
============ |
|
|
|
>>> from peak.context import Source, Line |
|
|
|
>>> s = Source("<test>", "def foo():\n def bar(): return 42\n return bar") |
|
>>> s |
|
Source('<test>') |
|
|
|
>>> list(s) |
|
['def foo():\n', ' def bar(): return 42\n', ' return bar'] |
|
|
|
>>> exec s.compile('exec') |
|
>>> bar = foo() |
|
>>> bar.func_code.co_firstlineno |
|
2 |
|
|
|
>>> s[1].strip() |
|
'def bar(): return 42' |
|
|
|
>>> _.line |
|
2 |
|
|
|
>>> (s[1]+'\n').splitlines()[1].line |
|
3 |
|
|
|
>>> exec(s[1].strip().compile('exec')) |
|
>>> bar.func_code.co_firstlineno |
|
2 |
|
|
|
>>> l = Line("lambda: (\n lambda: \n lambda: 42)", s, 19) |
|
>>> f = eval(l.compile('eval')) |
|
>>> f.func_code.co_firstlineno |
|
19 |
|
>>> f().func_code.co_firstlineno |
|
20 |
|
>>> f()().func_code.co_firstlineno |
|
21 |
|
>>> f()()() |
|
42 |
|
|
|
>>> from pkg_resources import yield_lines |
|
>>> list(yield_lines(s)) |
|
['def foo():', 'def bar(): return 42', 'return bar'] |
|
|
|
>>> _[2].line |
|
3 |
|
|
|
|
PEP 343 Implementation Tests |
PEP 343 Implementation Tests |