Metadata-Version: 1.1
Name: zope.app.xmlrpcintrospection
Version: 3.5.1
Summary: XML-RPC Method Introspection Support for Zope 3
Home-page: http://pypi.python.org/pypi/zope.app.xmlrpcintrospection
Author: Zope Corporation and Contributors
Author-email: zope-dev@zope.org
License: ZPL 2.1
Description: This Zope 3 package provides an XML-RPC introspection mechanism.
        
        
        Detailed Documentation
        ======================
        
        
        ====================
        XMLRPC Introspection
        ====================
        
        What's introspection now ?
        --------------------------
        
        This Zope 3 package provides an xmlrpcintrospection mechanism,
        as defined here:
        
            http://xmlrpc-c.sourceforge.net/xmlrpc-howto/xmlrpc-howto-api-introspection.html
        
        It registers three new xmlrpc methods:
        
            - `listMethods()`: Lists all xmlrpc methods (ie views) registered for the
              current object
        
            - `methodHelp(method_name)`: Returns the method documentation of the given
              method.
        
            - `methodSignature(method_name)`: Returns the method documentation of the
              given method.
        
        
        How do I use it ?
        -----------------
        
        Basically, if you want to add introspection into your XMLRPCView, you just
        have to add a decorator for each method of the view, that specifies the return
        type of the method and the argument types.
        
        The decorator is called `xmlrpccallable`
        
          >>> from zope.app.xmlrpcintrospection.xmlrpcintrospection import xmlrpccallable
          >>> from zope.app.publisher.xmlrpc import XMLRPCView
          >>> class MySuperXMLRPCView(XMLRPCView):
          ...     @xmlrpccallable(str, str, str, str)
          ...     def myMethod(self, a, b, c):
          ...         """ my help """
          ...         return '%s %s, %s, lalalala, you and me, lalalala' % (a, b, c)
        
        `myMethod()` will then be introspectable. (find a full examples below, grep
        for (*))
        
        
        How does it works ?
        -------------------
        
        It is based on introspection mechanisms provided by the apidoc package.
        
        ***** ripped form xmlrpc doctests *****
        
        Let's write a view that returns a folder listing:
        
          >>> class FolderListing:
          ...     def contents(self):
          ...         return list(self.context.keys())
        
        Now we'll register it as a view:
        
          >>> from zope.configuration import xmlconfig
          >>> ignored = xmlconfig.string("""
          ... <configure
          ...     xmlns="http://namespaces.zope.org/zope"
          ...     xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
          ...     >
          ...   <!-- We only need to do this include in this example,
          ...        Normally the include has already been done for us. -->
          ...   <include package="zope.app.publisher.xmlrpc" file="meta.zcml" />
          ...
          ...   <xmlrpc:view
          ...       for="zope.site.interfaces.IFolder"
          ...       methods="contents"
          ...       class="zope.app.xmlrpcintrospection.README.FolderListing"
          ...       permission="zope.ManageContent"
          ...       />
          ... </configure>
          ... """)
        
        Now, we'll add some items to the root folder:
        
          >>> print http(r"""
          ... POST /@@contents.html HTTP/1.1
          ... Authorization: Basic bWdyOm1ncnB3
          ... Content-Length: 73
          ... Content-Type: application/x-www-form-urlencoded
          ...
          ... type_name=BrowserAdd__zope.site.folder.Folder&new_value=f1""")
          HTTP/1.1 303 See Other
          ...
        
          >>> print http(r"""
          ... POST /@@contents.html HTTP/1.1
          ... Authorization: Basic bWdyOm1ncnB3
          ... Content-Length: 73
          ... Content-Type: application/x-www-form-urlencoded
          ...
          ... type_name=BrowserAdd__zope.site.folder.Folder&new_value=f2""")
          HTTP/1.1 303 See Other
          ...
        
        And call our xmlrpc method:
        
          >>> print http(r"""
          ... POST / HTTP/1.0
          ... Authorization: Basic bWdyOm1ncnB3
          ... Content-Length: 102
          ... Content-Type: text/xml
          ...
          ... <?xml version='1.0'?>
          ... <methodCall>
          ... <methodName>contents</methodName>
          ... <params>
          ... </params>
          ... </methodCall>
          ... """)
          HTTP/1.0 200 OK
          ...
          <?xml version='1.0'?>
          <methodResponse>
          <params>
          <param>
          <value><array><data>
          <value><string>f1</string></value>
          <value><string>f2</string></value>
          </data></array></value>
          </param>
          </params>
          </methodResponse>
          <BLANKLINE>
        
        ***** end of ripped form xmlrpc doctests *****
        
        Now we want to provide to that view introspection.
        Let's add three new xmlrcp methods, that published
        the introspection api.
        
          >>> ignored = xmlconfig.string("""
          ... <configure
          ...     xmlns="http://namespaces.zope.org/zope"
          ...     xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
          ...     >
          ...   <!-- We only need to do this include in this example,
          ...        Normally the include has already been done for us. -->
          ...   <include package="zope.app.publisher.xmlrpc" file="meta.zcml" />
          ...   <xmlrpc:view
          ...     for="zope.interface.Interface"
          ...     methods="listMethods  methodHelp methodSignature"
          ...     class="zope.app.xmlrpcintrospection.xmlrpcintrospection.XMLRPCIntrospection"
          ...     permission="zope.Public"
          ...     />
          ... </configure>
          ... """)
        
        They are linked to XMLRPCIntrospection class, that actually
         knows how to lookup to all interfaces
        
        And call our xmlrpc method, that should list the content method:
        
          >>> print http(r"""
          ... POST / HTTP/1.0
          ... Content-Type: text/xml
          ...
          ... <?xml version='1.0'?>
          ... <methodCall>
          ... <methodName>listMethods</methodName>
          ... <params>
          ... </params>
          ... </methodCall>
          ... """, handle_errors=False)
          HTTP/1.0 200 OK
          ...
          <?xml version='1.0'?>
          <methodResponse>
          ...
          <value><string>contents</string></value>
          ...
          </methodResponse>
          <BLANKLINE>
        
        Let's try to add another method, to se if it gets listed...
        
          >>> class FolderListing2:
          ...     def contents2(self):
          ...         return list(self.context.keys())
          >>> from zope.configuration import xmlconfig
          >>> ignored = xmlconfig.string("""
          ... <configure
          ...     xmlns="http://namespaces.zope.org/zope"
          ...     xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
          ...     >
          ...   <!-- We only need to do this include in this example,
          ...        Normally the include has already been done for us. -->
          ...   <include package="zope.app.publisher.xmlrpc" file="meta.zcml" />
          ...
          ...   <xmlrpc:view
          ...       for="zope.site.interfaces.IFolder"
          ...       methods="contents2"
          ...       class="zope.app.xmlrpcintrospection.README.FolderListing2"
          ...       permission="zope.ManageContent"
          ...       />
          ... </configure>
          ... """)
          >>> print http(r"""
          ... POST / HTTP/1.0
          ... Content-Type: text/xml
          ...
          ... <?xml version='1.0'?>
          ... <methodCall>
          ... <methodName>listMethods</methodName>
          ... <params>
          ... </params>
          ... </methodCall>
          ... """, handle_errors=False)
          HTTP/1.0 200 OK
          ...
          <?xml version='1.0'?>
          <methodResponse>
          ...
          <value><string>contents</string></value>
          <value><string>contents2</string></value>
          ...
          </methodResponse>
          <BLANKLINE>
        
        No we want to test methodHelp and methodSignature, to check that it returns,
        
            - The method doc
        
            - The list of attributes
        
        In RPC, the list of attributes has to be return in an array of type:
        
        [return type, param1 type, param2 type]
        
        Since in Python we cannot have a static type for the method return type,
        we introduce here a new mechanism based on a decorator, that let the xmlrpcview
        developer add his own signature.
        
        If the signature is not given, a defaut list is returned:
        
        [None, None, None...]
        
        The decorator append to the function objet two new parameters,
        to get back the signature.
        
          >>> from zope.app.xmlrpcintrospection.xmlrpcintrospection import xmlrpccallable
          >>> class JacksonFiveRPC:
          ...     @xmlrpccallable(str, str, str, str)
          ...     def says(self, a, b, c):
          ...         return '%s %s, %s, lalalala, you and me, lalalala' % (a, b, c)
        
        Let's try to get back the signature:
        
          >>> JacksonFiveRPC().says.return_type
          <type 'str'>
          >>> JacksonFiveRPC().says.parameters_types
          (<type 'str'>, <type 'str'>, <type 'str'>)
        
        The method is still callable as needed:
        
          >>> JacksonFiveRPC().says('a', 'b', 'c')
          'a b, c, lalalala, you and me, lalalala'
        
        Let's try out decorated and not decorated methods signatures (*):
        
          >>> class JacksonFiveRPC:
          ...     @xmlrpccallable(str, str, str, str)
          ...     def says(self, a, b, c):
          ...         return '%s %s, %s, lalalala, you and me, lalalala' % (a, b, c)
          ...     def says_not_decorated(self, a, b, c):
          ...         return '%s %s, %s, lalalala, you and me, lalalala' % (a, b, c)
          >>> from zope.configuration import xmlconfig
          >>> ignored = xmlconfig.string("""
          ... <configure
          ...     xmlns="http://namespaces.zope.org/zope"
          ...     xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
          ...     >
          ...   <!-- We only need to do this include in this example,
          ...        Normally the include has already been done for us. -->
          ...   <include package="zope.app.publisher.xmlrpc" file="meta.zcml" />
          ...
          ...   <xmlrpc:view
          ...       for="zope.site.folder.IFolder"
          ...       methods="says says_not_decorated"
          ...       class="zope.app.xmlrpcintrospection.README.JacksonFiveRPC"
          ...       permission="zope.ManageContent"
          ...       />
          ... </configure>
          ... """)
        
        Now let's try to get the signature for `says()`:
        
          >>> print http(r"""
          ... POST / HTTP/1.0
          ... Content-Type: text/xml
          ...
          ... <?xml version='1.0'?>
          ... <methodCall>
          ... <methodName>methodSignature</methodName>
          ... <params>
          ... <param>
          ... <value>says</value>
          ... </param>
          ... </params>
          ... </methodCall>
          ... """, handle_errors=False)
          HTTP/1.0 200 OK
          ...
          <?xml version='1.0'?>
          <methodResponse>
          <params>
          <param>
          <value><array><data>
          <value><array><data>
          <value><string>str</string></value>
          <value><string>str</string></value>
          <value><string>str</string></value>
          <value><string>str</string></value>
          </data></array></value>
          </data></array></value>
          </param>
          </params>
          </methodResponse>
          <BLANKLINE>
        
        Now let's try to get the signature for says_not_decorated()`:
        
          >>> print http(r"""
          ... POST / HTTP/1.0
          ... Content-Type: text/xml
          ...
          ... <?xml version='1.0'?>
          ... <methodCall>
          ... <methodName>methodSignature</methodName>
          ... <params>
          ... <param>
          ... <value>says_not_decorated</value>
          ... </param>
          ... </params>
          ... </methodCall>
          ... """, handle_errors=False)
          HTTP/1.0 200 OK
          ...
          <?xml version='1.0'?>
          <methodResponse>
          <params>
          <param>
          <value><array><data>
          <value><array><data>
          <value><string>undef</string></value>
          <value><string>undef</string></value>
          <value><string>undef</string></value>
          <value><string>undef</string></value>
          </data></array></value>
          </data></array></value>
          </param>
          </params>
          </methodResponse>
          <BLANKLINE>
        
        Last, but not least, the method help:
        
          >>> class JacksonFiveRPCDocumented:
          ...     @xmlrpccallable(str, str, str, str)
          ...     def says(self, a, b, c):
          ...         """ this is the help for
          ...             says()
          ...         """
          ...         return '%s %s, %s, lalalala, you and me, lalalala' % (a, b, c)
          ...     def says_not_documented(self, a, b, c):
          ...         return '%s %s, %s, lalalala, you and me, lalalala' % (a, b, c)
          >>> from zope.configuration import xmlconfig
          >>> ignored = xmlconfig.string("""
          ... <configure
          ...     xmlns="http://namespaces.zope.org/zope"
          ...     xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
          ...     >
          ...   <!-- We only need to do this include in this example,
          ...        Normally the include has already been done for us. -->
          ...   <include package="zope.app.publisher.xmlrpc" file="meta.zcml" />
          ...
          ...   <xmlrpc:view
          ...       for="zope.site.folder.IFolder"
          ...       methods="says says_not_documented"
          ...       class="zope.app.xmlrpcintrospection.README.JacksonFiveRPCDocumented"
          ...       permission="zope.ManageContent"
          ...       />
          ... </configure>
          ... """)
          >>> print http(r"""
          ... POST / HTTP/1.0
          ... Content-Type: text/xml
          ...
          ... <?xml version='1.0'?>
          ... <methodCall>
          ... <methodName>methodHelp</methodName>
          ... <params>
          ... <param>
          ... <value>says</value>
          ... </param>
          ... </params>
          ... </methodCall>
          ... """, handle_errors=False)
          HTTP/1.0 200 OK
          ...
          <?xml version='1.0'?>
          <methodResponse>
          <params>
          <param>
          <value><string> this is the help for
                       says()
                   </string></value>
          </param>
          </params>
          </methodResponse>
          <BLANKLINE>
          >>> print http(r"""
          ... POST / HTTP/1.0
          ... Content-Type: text/xml
          ...
          ... <?xml version='1.0'?>
          ... <methodCall>
          ... <methodName>methodHelp</methodName>
          ... <params>
          ... <param>
          ... <value>says_not_documented</value>
          ... </param>
          ... </params>
          ... </methodCall>
          ... """, handle_errors=False)
          HTTP/1.0 200 OK
          ...
          <?xml version='1.0'?>
          <methodResponse>
          <params>
          <param>
          <value><string>undef</string></value>
          </param>
          </params>
          </methodResponse>
          <BLANKLINE>
        
        
        
        =======
        CHANGES
        =======
        
        3.5.1 (2010-02-06)
        ------------------
        
        - Fix test by including zope.login
        - Include ftesting.zcml from zope.app.securitypolicy.browser.tests
        - Include meta.zcml from zope.securitypolicy 
        
        3.5.0 (2009-02-01)
        ------------------
        
        - Update ``zope.app.folder`` with ``zope.site``.
        
        3.4.0 (2007-11-03)
        ------------------
        
        - Initial release independent of the main Zope tree.
        
Keywords: zope3 xmlrpcintrospection site local component
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Zope Public License
Classifier: Programming Language :: Python
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Framework :: Zope3
