[pypy-svn] r40872 - pypy/dist/pypy/doc

hpk at codespeak.net hpk at codespeak.net
Wed Mar 21 08:34:43 CET 2007


Author: hpk
Date: Wed Mar 21 08:34:41 2007
New Revision: 40872

Modified:
   pypy/dist/pypy/doc/objspace-proxies.txt
Log:
first go at refactoring/streamlining Tproxies docs (and code)



Modified: pypy/dist/pypy/doc/objspace-proxies.txt
==============================================================================
--- pypy/dist/pypy/doc/objspace-proxies.txt	(original)
+++ pypy/dist/pypy/doc/objspace-proxies.txt	Wed Mar 21 08:34:41 2007
@@ -452,18 +452,19 @@
 Transparent Proxy Implementation
 ================================
 
-Among the unique features of PyPy, there is as well the possibility of
-having multiple implementations of builtin types. Multiple performance
-optimisations using this features are already implemented, see the document
-about `alternative object implementations`_.
-
-Transparent proxies are implementation of types which sends every performed
-operation on an object to a provided callable. From an application level
-it looks like an instance of arbitrary type, but all operations are directly
-calling a provided callable with an apropriate arguments.
+PyPy's Transparent Proxies allow to route operations to objects 
+to a callable.  Application level code can customize e.g. list
+and dictionary objects without interfering with the type system, 
+for example ``type(proxy_list) is list`` can be true but you 
+you have full control on all operations that are performed on the
+``proxy_list``.  
 
-Suppose we have a need of having a list instance which added to anything
-will provide 42. Than we create transparent proxy for int::
+
+Example of the core mechanism 
+-------------------------------------------
+
+The following example proxies a list and will 
+return ``42`` on any add operation to the list:: 
 
    $ py.py --with-transparent-proxy
    >>>> from pypymagic import transparent_proxy
@@ -473,65 +474,40 @@
    >>>>    raise AttributeError
    >>>>
    >>>> i = transparent_proxy(list, f)
-
-And now::
-
-   >>> type(i)
+   >>>> type(i)
    list
-   >>> i + 3
+   >>>> i + 3
    42
 
 .. _`alternative object implementations`: object-optimizations.html
 
-More sophisticated example:
----------------------------
+
+Example of recording all operations on builtins
+----------------------------------------------------
+
+XXX describe tputil.py's "Invocation" object somewhere 
+XXX this is work in progress
 
 Suppose we want to have list which stores all operations performed on
-it for later analysis. So we create an apropriate controller::
+it for later analysis.  We use a small `tputil.py`_ module that helps
+with transparently proxying builtin instances::
 
-   from pypymagic import transparent_proxy, get_transparent_controller
-   from types import MethodType
+   from tputil import make_proxy
 
-   class ListController(object):
-       def __init__(self, l):
-           assert isinstance(l, list)
-           self.l = l
-           self.history = []
-           self.proxy = transparent_proxy(list, self.perform)
-
-       def perform(self, operation, *args, **kwargs):
-           self.history.append(operation) # remember the operation performed
-           # perform the operation on the proxied object
-           result = getattr(self.l, operation)(*args, **kwargs)
-           if result is self.l:
-               # If the result is the proxied list
-               # return the proxy instead.
-               result = self.proxy
-           elif (isinstance(result, MethodType) and
-                 result.im_self is self.l):
-               # Convert methods bound to the proxied list
-               # to methods bound to the proxy.
-               # This is to have calls to the method become calls
-               # to perform.
-               result = MethodType(result.im_func, self.proxy, result.im_class)
-           return result
-
-   >>>> l = []
-   >>>> c = Controller(l)
-   >>>> lst = c.proxy
-
-Now we can perform::
-
-    >>>> lst.append(3)
-    >>>> len(lst)
-    1
-    >>>> l
-    [3]
-    >>>> c.history
-    [__getattribute__, append, __len__]
-    >>>> type(lst) is type(l)
-    True
+   history = []
+   def recorder(invocation):
+       history.append(invocation) 
+       return invocation.perform()
 
+   >>>> l = make_proxy([], recorder)
+   >>>> type(l)
+   list
+   >>>> l.append(3)
+   >>>> len(l)
+   1
+   >>>> len(history)
+   4
+   
 So what happened:
 
 * We've create transparent proxy of type list with controller c.perform
@@ -548,10 +524,13 @@
 does not show up at all (indeed the type is the only aspect of the instance that
 the controller cannot change).
 
-Provided API:
--------------
 
-Transparent proxy provides two magic functions appearing in the pypymagic module.
+Basic and tputil.py API 
+-----------------------------
+
+XXX (hpk) refactor/amend/refine 
+
+Transparent proxy provides two functions in the pypymagic module.
 
 * `transparent_proxy` - a basic function to create proxy object.
 
@@ -576,23 +555,34 @@
   objects. (Of course some operations on them could raise exceptions, but it's
   purely done in application level, so it's not real problem)
 
-Random notes:
--------------
+Implementation Note
+-----------------------------
 
-Transparent proxy is implemented on top of `standard object space`_, in
-`proxy_helpers.py`_, `proxyobject.py`_ and `transparent.py`_. To run it
-you need to pass ``--with-transparent-proxy`` option to ``py.py`` or
-``translate.py``. It registers implementations like a ``W_TransparentXxx``
-which usually corresponds to an apropriate ``W_XxxObject``, including some
-interpreter hacks for objects that are too close to the interpreter
-to be implemented in a std objspace. The types of objects that can be proxied
-like this are:
-user created classes & functions, lists, dicts, exceptions, tracebacks and
-frames.
+PyPy's standard object space allows to internally have multiple
+implementations of a type and change the implementation at run
+time while application level code consistently sees the exact 
+same type and object.  Multiple performance optimisations using 
+this features are already implemented, see the document
+about `alternative object implementations`_. Transparent
+Proxies use the architecture to provide control back 
+to application level code. 
+
+Transparent proxy is implemented on top of `standard object
+space`_, in `proxy_helpers.py`_, `proxyobject.py`_ and
+`transparent.py`_. To run it you need to pass
+``--with-transparent-proxy`` option to ``py.py`` or
+``translate.py``. It registers implementations like a
+``W_TransparentXxx`` which usually corresponds to an
+apropriate ``W_XxxObject``, including some interpreter hacks
+for objects that are too close to the interpreter to be
+implemented in a std objspace. The types of objects that can
+be proxied like this are: user created classes & functions,
+lists, dicts, exceptions, tracebacks and frames.
 
 .. _`standard object space`: objspace.html#the-standard-object-space
 .. _`proxy_helpers.py`: ../../pypy/objspace/std/proxy_helpers.py
 .. _`proxyobject.py`: ../../pypy/objspace/std/proxyobject.py
 .. _`transparent.py`: ../../pypy/objspace/std/transparent.py
+.. _`tputil.py`: ../../pypy/lib/tputil.py
 
 .. include:: _ref.txt



More information about the Pypy-commit mailing list