[Subversion] / Contextual / README.txt  

Diff of /Contextual/README.txt

Parent Directory | Revision Log

version 2278, Wed Jan 24 03:06:24 2007 UTC version 2279, Sat Feb 24 05:37:44 2007 UTC
Line 28 
Line 28 
 So, most of us end up stuck between various unpalatable choices:  So, most of us end up stuck between various unpalatable choices:
   
 1. use a global and get it over with (but suffer a guilty conscience and  1. use a global and get it over with (but suffer a guilty conscience and
    the fear of later disasters in retribution for our sins), or     the fear of later disasters in retribution for our sins),
   
 2. attempt to use a dependency injection framework, paying extra now to be  2. attempt to use a dependency injection framework, paying extra now to be
    reassured that things will work out later.     reassured that things will work out later, or
   
 3. use a thread-local variable, and bear the cost of introducing a possible  3. use a thread-local variable, and bear the cost of introducing a possible
    threading dependency, and still not having a reasonable way to test or     threading dependency, and still not having a reasonable way to test or
Line 61 
Line 61 
 Replaceable Singletons  Replaceable Singletons
 ----------------------  ----------------------
   
 Here's what a simple "global" counter object implemented with ``peak.context``  Here's what a simple "global" counter service implemented with ``peak.context``
 looks like::  looks like::
   
     >>> from peak.util import context      >>> from peak import context
   
     >>> class Counter(context.Replaceable):      >>> class Counter(context.Service):
     ...     value = 0      ...     value = 0
     ...      ...
     ...     def inc(self):      ...     def inc(self):
       ...         "test"
     ...         self.value += 1      ...         self.value += 1
     ...      ...
   
     >>> count = Counter.proxy()      >>> Counter.value
   
     >>> count.value  
     0      0
     >>> count.inc()      >>> Counter.inc()
     >>> count.value      >>> Counter.value
     1      1
   
 Code that wants to use this global counter just calls ``count.inc()`` or  Code that wants to use this global counter just calls ``Counter.inc()`` or
 accesses ``count.value``, and it will automatically use the right ``Counter``  accesses ``Counter.value``, and it will automatically use the right ``Counter``
 instance for the current thread or task.  Want to use a fresh counter for  instance for the current thread or task.  Want to use a fresh counter for
 a test?  Just do this::  a test?  Just do this::
   
Line 94 
Line 93 
 ``context`` library also includes a decorator that emulates a ``with``  ``context`` library also includes a decorator that emulates a ``with``
 statement::  statement::
   
     >>> count.value     # before using a different counter      >>> Counter.value     # before using a different counter
     1      1
   
     >>> @context.call_with(Counter())      >>> @context.call_with(Counter())
     ... def do_it(c):      ... def do_it(c):
     ...     print count.value      ...     print Counter.value
     0      0
   
     >>> count.value     # The original counter is now in use again      >>> Counter.value     # The original counter is now in use again
     1      1
   
 The ``@call_with`` decorator is a bit uglier than a ``with`` statement, but  The ``@call_with`` decorator is a bit uglier than a ``with`` statement, but
Line 117 
Line 116 
 Want to create an alternative implementation of the same service, that can  Want to create an alternative implementation of the same service, that can
 be plugged in to replace it?  That's simple too::  be plugged in to replace it?  That's simple too::
   
     >>> class DoubleCounter(context.Replaceable):      >>> class DoubleCounter(context.Service):
     ...     context.replaces(Counter)      ...     context.replaces(Counter)
     ...     value = 0      ...     value = 0
     ...     def inc(self):      ...     def inc(self):
Line 134 
Line 133 
   
     >>> @context.call_with(DoubleCounter())      >>> @context.call_with(DoubleCounter())
     ... def do_it(c):      ... def do_it(c):
     ...     print count.value      ...     print Counter.value
     ...     count.inc()      ...     Counter.inc()
     ...     print count.value      ...     print Counter.value
     0      0
     2      2
   
 And of course, once a replacement is no longer in use, the original instance  And of course, once a replacement is no longer in use, the original instance
 becomes active again::  becomes active again::
   
     >>> count.value      >>> Counter.value
     1      1
   
 All this, with no interfaces to declare or register, and no XML or  All this, with no interfaces to declare or register, and no XML or
Line 154 
Line 153 
 want.  You can even take a snapshot of the entire current context and restore  want.  You can even take a snapshot of the entire current context and restore
 all the previous values::  all the previous values::
   
     old = context.swap(context.new())      with context.Globals():
     try:  
         # code to read config file and set ``current()`` services          # code to read config file and set ``current()`` services
         # code that uses the configured services          # code that uses the configured services
     finally:  
         context.swap(old)   # restore the previous context  
   
 This code won't share any "globals" with the code that calls it; it will not  This code won't share any "globals" with the code that calls it; it will not
 only get its own private ``Counter`` instance, but a private instance of any  only get its own private ``Counter`` instance, but a private instance of any
 other ``Replaceable`` objects it uses as well.  (Instances are created lazily  other ``Service`` objects it uses as well.  (Instances are created lazily
 in new contexts, so if you don't use a particular service, it's never created.)  in new contexts, so if you don't use a particular service, it's never created.)
 Try doing that with global or thread-local variables!  Try doing that with global or thread-local variables!
   


Generate output suitable for use with a patch program
Legend:
Removed from v.2278  
changed lines
  Added in v.2279

cvs-admin@eby-sarna.com

Powered by ViewCVS 1.0-dev

ViewCVS and CVS Help