Browse Source

Added TwistedSOAPPublisher

main
Jarrod Chesney 8 years ago
parent
commit
e3e415ca1e
22 changed files with 204 additions and 46 deletions
  1. +8
    -0
      CHANGES.txt
  2. +0
    -1
      bid/.cvsignore
  3. +0
    -1
      contrib/.cvsignore
  4. +17
    -14
      setup.py
  5. +4
    -4
      src/SOAPpy/Client.py
  6. +1
    -1
      src/SOAPpy/GSIServer.py
  7. +1
    -1
      src/SOAPpy/NS.py
  8. +2
    -2
      src/SOAPpy/Parser.py
  9. +4
    -4
      src/SOAPpy/SOAP.py
  10. +1
    -1
      src/SOAPpy/SOAPBuilder.py
  11. +2
    -2
      src/SOAPpy/Server.py
  12. +41
    -0
      src/SOAPpy/TwistedSOAPProxy.py
  13. +98
    -0
      src/SOAPpy/TwistedSOAPPublisher.py
  14. +18
    -6
      src/SOAPpy/Types.py
  15. +1
    -1
      src/SOAPpy/Utilities.py
  16. +1
    -1
      src/SOAPpy/version.py
  17. +1
    -1
      tests/SOAPtest.py
  18. +1
    -1
      tests/alanbushTest.py
  19. +1
    -1
      tests/storageTest.py
  20. +2
    -2
      tests/testClient1.py
  21. +0
    -1
      tools/.cvsignore
  22. +0
    -1
      validate/.cvsignore

+ 8
- 0
CHANGES.txt View File

@@ -1,6 +1,14 @@
CHANGELOG
=====================

0.52.23 (unreleased)
--------------------

- Port to Python 3.5
- Added TwistedSOAPPublisher and Proxy
These are located in twisted.web.soap, but thats only for Python 2.


0.12.23 (unreleased)
--------------------



+ 0
- 1
bid/.cvsignore View File

@@ -1 +0,0 @@
*.pyc

+ 0
- 1
contrib/.cvsignore View File

@@ -1 +0,0 @@
*.pyc

+ 17
- 14
setup.py View File

@@ -2,33 +2,36 @@
#
# $Id: setup.py,v 1.11 2005/02/15 16:32:22 warnes Exp $

CVS=0
CVS = 0

from setuptools import setup, find_packages
import os

from setuptools import setup, find_packages


def read(*rnames):
return "\n"+ open(
return "\n" + open(
os.path.join('.', *rnames)
).read()
url="https://github.com/kiorky/SOAPpy.git"
long_description="SOAPpy provides tools for building SOAP clients and servers. For more information see " + url\
+'\n'+read('README.txt')\
+'\n'+read('CHANGES.txt')


url = "https://github.com/Synerty/SOAPpy-py3"
long_description = "SOAPpy-py3 provides tools for building SOAP clients and servers. For more information see " + url \
+ '\n' + read('README.txt') \
+ '\n' + read('CHANGES.txt')
setup(
name="SOAPpy",
version='0.12.23.dev0',
name="SOAPpy-py3",
version='0.52.23', # Add 0.40.0 for the SOAPpy-py3 port
description="SOAP Services for Python",
maintainer="Gregory Warnes, kiorky",
maintainer_email="Gregory.R.Warnes@Pfizer.com, kiorky@cryptelium.net",
url = url,
maintainer="Synerty",
maintainer_email="contact@synerty.com",
url=url,
long_description=long_description,
packages=find_packages('src'),
package_dir = {'': 'src'},
package_dir={'': 'src'},
include_package_data=True,
install_requires=[
'wstools',
'defusedxml',
]
)


+ 4
- 4
src/SOAPpy/Client.py View File

@@ -55,7 +55,7 @@ import socket, http.client
from http.client import HTTPConnection
import http.cookies

# SOAPpy modules
# SOAPpy-py3 modules
from .Errors import *
from .Config import Config
from .Parser import parseSOAPRPC
@@ -71,7 +71,7 @@ import collections


def SOAPUserAgent():
return "SOAPpy " + __version__ + " (pywebsvcs.sf.net)"
return "SOAPpy-py3 " + __version__ + " (pywebsvcs.sf.net)"


class HTTP:
@@ -137,7 +137,7 @@ class HTTP:
#only add this keyword if non-default for compatibility
#with other connection classes
response = self._conn.getresponse(buffering)
except BadStatusLine as e:
except http.BadStatusLine as e:
### hmm. if getresponse() ever closes the socket on a bad request,
### then we are going to have problems with self.sock

@@ -329,7 +329,7 @@ class HTTPTransport:
debugHeader(s)
print("POST %s %s" % (real_path, r._http_vsn_str))
print("Host:", addr.host)
print("User-agent: SOAPpy " + __version__ + " (http://pywebsvcs.sf.net)")
print("User-agent: SOAPpy-py3 " + __version__ + " (http://pywebsvcs.sf.net)")
print("Content-type:", t)
print("Content-length:", len(data))
print('SOAPAction: "%s"' % soapaction)


+ 1
- 1
src/SOAPpy/GSIServer.py View File

@@ -56,7 +56,7 @@ import socketserver
from SOAPpy.Types import *
import http.server

# SOAPpy modules
# SOAPpy-py3 modules
from .Parser import parseSOAPRPC
from .Config import SOAPConfig
from .Types import faultType, voidType, simplify


+ 1
- 1
src/SOAPpy/NS.py View File

@@ -40,7 +40,7 @@
################################################################################

"""
from SOAPpy.Errors import Error

ident = '$Id: NS.py 1468 2008-05-24 01:55:33Z warnes $'
from .version import __version__


+ 2
- 2
src/SOAPpy/Parser.py View File

@@ -298,7 +298,7 @@ class SOAPParser(xml.sax.handler.ContentHandler):

if null:
if len(cur) or \
(self._data != None and string.join(self._data, "").strip() != ''):
(self._data != None and ''.join(self._data).strip() != ''):
raise Error("nils can't have data")

data = None
@@ -943,7 +943,7 @@ class SOAPParser(xml.sax.handler.ContentHandler):
raise OverflowError("%s too large: %s" % (t[1], s))
elif d == 0:
if type(self.zerofloatre) == StringType:
self.zerofloatre = re.compile(self.zerofloatre)
self.zerofloatre = re.compile(str(self.zerofloatre))

if self.zerofloatre.search(s):
raise UnderflowError("invalid %s: %s" % (t[1], s))


+ 4
- 4
src/SOAPpy/SOAP.py View File

@@ -22,17 +22,17 @@ from warnings import warn

warn("""

The sub-module SOAPpy.SOAP is deprecated and is only
The sub-module SOAPpy-py3.SOAP is deprecated and is only
provided for short-term backward compatibility. Objects are now
available directly within the SOAPpy module. Thus, instead of
available directly within the SOAPpy-py3 module. Thus, instead of

from SOAPpy import SOAP
from SOAPpy-py3 import SOAP
...
SOAP.SOAPProxy(...)

use

from SOAPpy import SOAPProxy
from SOAPpy-py3 import SOAPProxy
...
SOAPProxy(...)



+ 1
- 1
src/SOAPpy/SOAPBuilder.py View File

@@ -39,7 +39,7 @@ from .version import __version__
import cgi
from wstools.XMLname import toXMLname, fromXMLname

# SOAPpy modules
# SOAPpy-py3 modules
from .Config import Config
from .NS import NS
from SOAPpy.Types import *


+ 2
- 2
src/SOAPpy/Server.py View File

@@ -53,7 +53,7 @@ from SOAPpy.Types import *
import http.server
import _thread

# SOAPpy modules
# SOAPpy-py3 modules
from .Parser import parseSOAPRPC
from .Config import Config
from SOAPpy.Types import faultType, voidType, simplify
@@ -194,7 +194,7 @@ class SOAPRequestHandler(http.server.BaseHTTPRequestHandler):
ignore_ext = True
def version_string(self):
return '<a href="http://pywebsvcs.sf.net">' + \
'SOAPpy ' + __version__ + '</a> (Python ' + \
'SOAPpy-py3 ' + __version__ + '</a> (Python ' + \
sys.version.split()[0] + ')'

def date_time_string(self):


+ 41
- 0
src/SOAPpy/TwistedSOAPProxy.py View File

@@ -0,0 +1,41 @@
# twisted imports
from twisted.web import client

import SOAPpy


class TwistedSOAPProxy:
"""A Proxy for making remote SOAP calls.
Pass the URL of the remote SOAP server to the constructor.
Use proxy.callRemote('foobar', 1, 2) to call remote method
'foobar' with args 1 and 2, proxy.callRemote('foobar', x=1)
will call foobar with named argument 'x'.
"""

# at some point this should have encoding etc. kwargs
def __init__(self, url, namespace=None, header=None):
self.url = url
self.namespace = namespace
self.header = header

def _cbGotResult(self, result):
result = SOAPpy.parseSOAPRPC(result)
if hasattr(result, 'Result'):
return result.Result
elif len(result) == 1:
## SOAPpy 0.11.6 wraps the return results in a containing structure.
## This check added to make Proxy behaviour emulate SOAPProxy, which
## flattens the structure by default.
## This behaviour is OK because even singleton lists are wrapped in
## another singleton structType, which is almost always useless.
return result[0]
else:
return result

def callRemote(self, method: str, *args, **kwargs):
payload = SOAPpy.buildSOAP(args=args, kw=kwargs, method=method,
header=self.header, namespace=self.namespace)
return client.getPage(self.url.encode, postdata=payload, method=b"POST",
headers={b'content-type': b'text/xml',
b'SOAPAction': method.encode()}
).addCallback(self._cbGotResult)

+ 98
- 0
src/SOAPpy/TwistedSOAPPublisher.py View File

@@ -0,0 +1,98 @@
# twisted imports
import logging

from twisted.internet import defer
from twisted.web import server, resource

import SOAPpy

class TwistedSOAPPublisher(resource.Resource):
"""Publish SOAP methods.
By default, publish methods beginning with 'soap_'. If the method
has an attribute 'useKeywords', it well get the arguments passed
as keyword args.
"""

isLeaf = 1

# override to change the encoding used for responses
encoding = "UTF-8"

def lookupFunction(self, functionName):
"""Lookup published SOAP function.
Override in subclasses. Default behaviour - publish methods
starting with soap_.
@return: callable or None if not found.
"""
return getattr(self, "soap_%s" % functionName, None)

def render(self, request):
"""Handle a SOAP command."""
data = request.content.read()

# Convert it to str from bytes
data = data.decode()

p, header, body, attrs = SOAPpy.parseSOAPRPC(data, 1, 1, 1)

methodName, args, kwargs = p._name, p._aslist, p._asdict

# deal with changes in SOAPpy 0.11
if callable(args):
args = args()
if callable(kwargs):
kwargs = kwargs()

function = self.lookupFunction(methodName)

if not function:
self._methodNotFound(request, methodName)
return server.NOT_DONE_YET
else:
if hasattr(function, "useKeywords"):
keywords = {}
for k, v in kwargs.items():
keywords[str(k)] = v
d = defer.maybeDeferred(function, **keywords)
else:
d = defer.maybeDeferred(function, *args)

d.addCallback(self._gotResult, request, methodName)
d.addErrback(self._gotError, request, methodName)
return server.NOT_DONE_YET

def _methodNotFound(self, request, methodName):
response = SOAPpy.buildSOAP(SOAPpy.faultType("%s:Client" %
SOAPpy.NS.ENV_T,
"Method %s not found" % methodName),
encoding=self.encoding)
self._sendResponse(request, response, status=500)

def _gotResult(self, result, request, methodName):
if not isinstance(result, SOAPpy.voidType):
result = {"Result": result}
response = SOAPpy.buildSOAP(kw={'%sResponse' % methodName: result},
encoding=self.encoding)
self._sendResponse(request, response)

def _gotError(self, failure, request, methodName):
e = failure.value
if isinstance(e, SOAPpy.faultType):
fault = e
else:
fault = SOAPpy.faultType("%s:Server" % SOAPpy.NS.ENV_T,
"Method %s failed." % methodName)
response = SOAPpy.buildSOAP(fault, encoding=self.encoding)
self._sendResponse(request, response, status=500)

def _sendResponse(self, request, response, status=200):
request.setResponseCode(status)

if self.encoding is not None:
mimeType = 'text/xml; charset="%s"' % self.encoding
else:
mimeType = "text/xml"
request.setHeader(b"Content-type", mimeType.encode())
request.setHeader(b"Content-length", str(len(response)).encode())
request.write(response)
request.finish()

+ 18
- 6
src/SOAPpy/Types.py View File

@@ -34,6 +34,18 @@

"""

## PYTHON3 - These types are no longer present in the builtin "types" module

StringType = str
UnicodeType = str
ListType = list
DictType = dict
IntType = int
LongType = int
FloatType = float
BooleanType = bool
TupleType = tuple
InstanceType = object

ident = '$Id: Types.py 1496 2010-03-04 23:46:17Z pooryorick $'
from .version import __version__
@@ -47,7 +59,7 @@ import re
import time
from SOAPpy.Types import *

# SOAPpy modules
# SOAPpy-py3 modules
from .Errors import *
from .NS import NS
from .Utilities import encodeHexString, cleanDate
@@ -1110,7 +1122,7 @@ class longType(anyType):

return data

class int(anyType):
class intType(anyType):
_validURIs = (NS.XSD2, NS.XSD3, NS.ENC)

def _checkValueSpace(self, data):
@@ -1611,7 +1623,7 @@ class faultType(structType, Error):

class SOAPException(Exception):
def __init__(self, code="", string="", detail=None):
self.value = ("SOAPpy SOAP Exception", code, string, detail)
self.value = ("SOAPpy-py3 SOAP Exception", code, string, detail)
self.code = code
self.string = string
self.detail = detail
@@ -1650,12 +1662,12 @@ class MethodFailed(Exception):
return repr(self.value)
#######
# Convert complex SOAPpy objects to native python equivalents
# Convert complex SOAPpy-py3 objects to native python equivalents
#######

def simplify(object, level=0):
"""
Convert the SOAPpy objects and their contents to simple python types.
Convert the SOAPpy-py3 objects and their contents to simple python types.

This function recursively converts the passed 'container' object,
and all public subobjects. (Private subobjects have names that
@@ -1709,7 +1721,7 @@ def simplify(object, level=0):

def simplify_contents(object, level=0):
"""
Convert the contents of SOAPpy objects to simple python types.
Convert the contents of SOAPpy-py3 objects to simple python types.

This function recursively converts the sub-objects contained in a
'container' object to simple python types.


+ 1
- 1
src/SOAPpy/Utilities.py View File

@@ -41,7 +41,7 @@ import string
import sys
from SOAPpy.Types import *

# SOAPpy modules
# SOAPpy-py3 modules
from .Errors import *

################################################################################


+ 1
- 1
src/SOAPpy/version.py View File

@@ -1,5 +1,5 @@
try:
import pkg_resources
__version__ = pkg_resources.get_distribution("SOAPpy").version
__version__ = pkg_resources.get_distribution("SOAPpy-py3").version
except:
__version__="xxx"

+ 1
- 1
tests/SOAPtest.py View File

@@ -3750,7 +3750,7 @@ if __name__ == '__main__':

NOTE: The 'testArray' test will fail because 'referenced' elements are
included in the return object. This is a known shortcoming of
the current version of SOAPpy.
the current version of SOAPpy-py3.

All other tests should succeed.



+ 1
- 1
tests/alanbushTest.py View File

@@ -6,7 +6,7 @@ ident = '$Id: alanbushTest.py,v 1.5 2003/05/21 14:52:37 warnes Exp $'

import os, re,sys

# add local SOAPpy code to search path
# add local SOAPpy-py3 code to search path
sys.path.insert(1, "..")

from SOAPpy import *


+ 1
- 1
tests/storageTest.py View File

@@ -16,7 +16,7 @@ except:


PROXY="http://www.soapware.org/xmlStorageSystem"
EMAIL="SOAPpy@actzero.com"
EMAIL="SOAPpy-py3@actzero.com"
NAME="test_user"
PASSWORD="mypasswd"
SERIAL=1123214


+ 2
- 2
tests/testClient1.py View File

@@ -7,7 +7,7 @@ import sys
sys.path.insert(1, "..")

import SOAPpy
#SOAPpy.Config.debug=1
#SOAPpy-py3.Config.debug=1

# global to shut down server
quit = 0
@@ -107,7 +107,7 @@ class ClientTestCase(unittest.TestCase):

# gc.set_debug(gc.DEBUG_SAVEALL)
# for i in range(400):
# server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000')
# server = SOAPpy-py3.Client.SOAPProxy('127.0.0.1:8000')
# s = 'Hello World'
# server.echo(s)
# gc.collect()


+ 0
- 1
tools/.cvsignore View File

@@ -1 +0,0 @@
*.pyc

+ 0
- 1
validate/.cvsignore View File

@@ -1 +0,0 @@
*.pyc

Loading…
Cancel
Save