[Zope-Checkins] CVS: Zope3/lib/python/Zope/Publisher/SOAP - ISOAPPublisher.py:1.1.2.1 MethodPublisher.py:1.1.2.1 SOAPPayload.py:1.1.2.1 __init__.py:1.1.2.1 metaConfigure.py:1.1.2.1 soap-meta.zcml:1.1.2.1 soaplib.py:1.1.2.1

Stephan Richter srichter@cbu.edu
Wed, 13 Mar 2002 05:57:36 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/Publisher/SOAP
In directory cvs.zope.org:/tmp/cvs-serv11175/lib/python/Zope/Publisher/SOAP

Added Files:
      Tag: srichter-OFS_Formulator-branch
	ISOAPPublisher.py MethodPublisher.py SOAPPayload.py 
	__init__.py metaConfigure.py soap-meta.zcml soaplib.py 
Log Message:
- Added some more tests. Won;t do more, since Publisher is being redesigned
  later this week. I will wait until then.

- Added preliminary SOAP support, so we can test Mozilla's SOAP 
  capabilities. Unfortunately, soaplib is very old; I will look into using 
  SOAPpy instead. It seems fairly complete.


=== Added File Zope3/lib/python/Zope/Publisher/SOAP/ISOAPPublisher.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. 
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""

$Id: ISOAPPublisher.py,v 1.1.2.1 2002/03/13 10:57:34 srichter Exp $
"""
from Interface import Interface


class ISOAPPublisher(Interface):
    """This is very similar to the Browser version;
    """

    def soap_traverse(request, name):
        """Lookup a name
        """


    def soap_default(request):
        """Provide the default object

        """



=== Added File Zope3/lib/python/Zope/Publisher/SOAP/MethodPublisher.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. 
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""

$Id: MethodPublisher.py,v 1.1.2.1 2002/03/13 10:57:34 srichter Exp $
"""
from ISOAPPublisher import ISOAPPublisher

class MethodPublisher:

    __implements__ = ISOAPPublisher

    # Implementation methods for interface
    # Zope.Publisher.SOAP.ISOAPPublisher.

    def soap_traverse(self, request, name):
        '''See interface ISOAPPublisher'''

        return getattr(self, name)


    def soap_default(self, request):
        '''See interface ISOAPPublisher'''
        return self, ("info",)


=== Added File Zope3/lib/python/Zope/Publisher/SOAP/SOAPPayload.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. 
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""
SOAP Request/Response Handler

$Id: SOAPPayload.py,v 1.1.2.1 2002/03/13 10:57:34 srichter Exp $
"""
from types import ClassType, ListType, StringType
from cgi import FieldStorage, escape
from Zope.Publisher.HTTP.cgi_names import hide_key
import soaplib

from Zope.Publisher.HTTP.IPayload import IRequestPayload, IResponsePayload
from Zope.Publisher.Converters import get_converter
from Zope.Publisher.Exceptions import Redirect, Unauthorized

from ISOAPPublisher import ISOAPPublisher 


class SOAPRequestPayload:
    """
    Works with the body of a XML-RPC request.
    """

    __implements__ = IRequestPayload

    _viewtype = ISOAPPublisher
    

    def __init__(self, publication):
        self.publication = publication


    def processInputs(self, request, fs=None):
        """
        Processes form data
        """
        environ = request.environ
        form = request.form
        other = request.other
        method = environ.get('REQUEST_METHOD', 'GET')

        if fs is None:
            if method != 'GET':
                # Process form if not a GET request.
                fp = request.body_instream
            else:
                fp = None
            fs = FieldStorage(fp=fp, environ=environ, keep_blank_values=1)

        # Parse the request XML structure
        function, request.args = soaplib.loads(fs.value)
        print request.args
        print function
        # Translate '.' to '/' in function to represent object traversal.
        function = function.replace('.', '/')

        other['REQUEST_METHOD']='' # We don't want index_html!
                     
        other.update(form)
        if function:
            request.setRequestDefault(function)


    def getPublication(self, request):
        return self.publication


    def debugInfo(self, request):
        result = "<p>URL: %s</p>" % request.URL
        result = result + "<p>SERVER_URL: %s</p>" % request.SERVER_URL
        return result


    def setViewType(self, viewtype):
        self._viewtype = viewtype


    def getViewType(self):
        return self._viewtype

            

class SOAPResponsePayload:
    """Customized Response that handles XML-RPC-specific details.

    We override setBody to marhsall Python objects into XML-RPC. We
    also override exception to convert errors to XML-RPC faults.

    If these methods stop getting called, make sure that ZPublisher is
    using the soap.Response object created above and not the original
    HTTPResponse object from which it was cloned.

    It's probably possible to improve the 'exception' method quite a bit.
    The current implementation, however, should suffice for now.
    """

    __implements__ = IResponsePayload


    def setBody(self, response, body):
        """ """

        if isinstance(body, soaplib.Fault):
            # Convert Fault object to XML-RPC response.
            body = soaplib.dumps(body, envelope=1)
        else:
            try:
                body = soaplib.dumps((body,), envelope=1)
            except:
                self.exception()
                return

        # Set our body to the XML-RPC message, and fix our MIME type.
        response.body = body

        # client identifier (may be overridden)
        user_agent = "soaplib.py/0.8 (from www.pythonware.com)"
	# required by SOAP
	response.setHeader("User-Agent", user_agent)
	response.setHeader("Content-Type", "text/xml")
	response.setHeader("Content-Length", str(len(body)))
	response.setHeader("SOAPAction", '""')
        return response


    def handleException(self, response, exc_info):
        """
        """
        t, value = exc_info[:2]

        import traceback
        traceback.print_tb(exc_info[2])
        print t
        print value

        # Create an appropriate Fault object. Unfortunately, we throw away
        # most of the debugging information. More useful error reporting is
        # left as an exercise for the reader.
        Fault = soaplib.Fault
        fault_text = None
        try:
            if isinstance(value, Fault):
                fault_text = value
            elif isinstance(value, Exception):
                fault_text = Fault(-1, "Unexpected Zope exception: " + str(value))
            else:
                fault_text = Fault(-2, "Unexpected Zope error value: " + str(value))
        except:
            fault_text = Fault(-3, "Unknown Zope fault type")

        # Do the damage.
        response.setBody(fault_text)
        response.setStatus(200)


=== Added File Zope3/lib/python/Zope/Publisher/SOAP/__init__.py ===
# Copyright (c) 2001 Zope Corporation and Contributors.  All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 1.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.

#from IBrowserPublisher import IBrowserPublisher


=== Added File Zope3/lib/python/Zope/Publisher/SOAP/metaConfigure.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. 
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""

$Id: metaConfigure.py,v 1.1.2.1 2002/03/13 10:57:34 srichter Exp $
"""
from Zope.ComponentArchitecture import provideView, setDefaultViewName
from Zope.Configuration.name import resolve
from Zope.Configuration.Action import Action
from ISOAPPublisher import ISOAPPublisher


def defaultView(name, factory, for_=None, layer=''):
    if for_ is not None:
        for_ = resolve(for_)
    factory = map(resolve, factory.split(' '))
    
    return [
        Action(
            discriminator = ('view', for_, name, ISOAPPublisher),
            callable = provideView, 
            args = (for_, name, ISOAPPublisher, factory, layer),
            ),
        Action(
            discriminator = ('defaultViewName', for_, name, ISOAPPublisher),
            callable = setDefaultViewName,
            args = (for_, ISOAPPublisher, name),
            )
        ]

    
def view(name, factory, for_=None, layer=''):
    if for_ is not None:
        for_ = resolve(for_)
    factory = map(resolve, factory.split(' '))

    return [
        Action(
            discriminator = ('view', for_, name, ISOAPPublisher, layer),
            callable = provideView,
            args = (for_, name, ISOAPPublisher, factory, layer),
            )
        ]


=== Added File Zope3/lib/python/Zope/Publisher/SOAP/soap-meta.zcml ===
<zopeConfigure xmlns='http://namespaces.zope.org/zope'>
  
  <!-- Zope.Publisher.SOAP -->
  <directives namespace="http://namespaces.zope.org/soap">
    <directive name="view" attributes="factory, name, for"
       handler="Zope.Publisher.SOAP.metaConfigure.view" />
    <directive name="defaultView" attributes="factory, name, for"
       handler="Zope.Publisher.SOAP.metaConfigure.defaultView" />
  </directives>

</zopeConfigure>


=== Added File Zope3/lib/python/Zope/Publisher/SOAP/soaplib.py === (769/869 lines abridged)
#
# SOAP CLIENT LIBRARY
# $Id: soaplib.py,v 1.1.2.1 2002/03/13 10:57:34 srichter Exp $
#
# an SOAP 1.1 client interface for Python.
#
# the marshalling and response parser code can also be used to
# implement SOAP servers.
#
# Notes:
# this version uses the sgmlop XML parser, if installed.  this is
# typically 10-15x faster than using Python's standard XML parser.
#
# you can get the sgmlop distribution from:
#
#    http://www.pythonware.com/products/xml
#
# also note that this version is designed to work with Python 1.5.2
# and newer.  it does not work under 1.5.1 or earlier.
#
# Contact:
# fredrik@pythonware.com
# http://www.pythonware.com
#
# History:
# 2000-01-05 fl  First experimental version (based on xmlrpclib.py)
# 2000-02-15 fl  Updated to SOAP 1.0
# 2000-04-30 fl  Major overhaul, updated for SOAP 1.1
# 2000-05-27 fl  Fixed xmllib support
# 2000-06-20 fl  Frontier interoperability testing
#
# Copyright (c) 1999-2000 by Secret Labs AB.
# Copyright (c) 1999-2000 by Fredrik Lundh.
#
# Portions of this engine have been developed in cooperation with
# Loudcloud, Inc.
#
# --------------------------------------------------------------------
# The soaplib.py library is
# 
# Copyright (c) 1999-2000 by Secret Labs AB
# Copyright (c) 1999-2000 by Fredrik Lundh
#
# By obtaining, using, and/or copying this software and/or its
# associated documentation, you agree that you have read, understood,
# and will comply with the following terms and conditions:
#
# Permission to use, copy, modify, and distribute this software and
# its associated documentation for any purpose and without fee is
# hereby granted, provided that the above copyright notice appears in

[-=- -=- -=- 769 lines omitted -=- -=- -=-]



    def _defmethod(self, methodname, namespace):
	# associate information with a remote methodname

	self.__methods[methodname] = namespace


    def __request(self, methodname, pargs, kwargs):
	# call a method on the remote server

	# wrap the arguments up
	params = MethodCall(
	    methodname, self.__methods.get(methodname), pargs, kwargs
	    )

	request = dumps(params, 1)

	response = self.__transport.request(
	    self.__host,
	    self.__handler,
	    request
	    )

	return response


    def __repr__(self):
	return (
	    "<Server proxy for %s%s>" %
	    (self.__host, self.__handler)
	    )

    __str__ = __repr__


    def __getattr__(self, name):
	# magic method dispatcher
	return _Method(self.__request, name)


    def __getitem__(self, name):
	# alternate method dispatcher
	return _Method(self.__request, name)



# xmlrpclib compatibility
Server = ServerProxy