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 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.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 $ # $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 import os


from setuptools import setup, find_packages


def read(*rnames): def read(*rnames):
return "\n"+ open(
return "\n" + open(
os.path.join('.', *rnames) os.path.join('.', *rnames)
).read() ).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( 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", 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, long_description=long_description,
packages=find_packages('src'), packages=find_packages('src'),
package_dir = {'': 'src'},
package_dir={'': 'src'},
include_package_data=True, include_package_data=True,
install_requires=[ install_requires=[
'wstools', 'wstools',
'defusedxml', 'defusedxml',
] ]
) )


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

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


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




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




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


@@ -329,7 +329,7 @@ class HTTPTransport:
debugHeader(s) debugHeader(s)
print("POST %s %s" % (real_path, r._http_vsn_str)) print("POST %s %s" % (real_path, r._http_vsn_str))
print("Host:", addr.host) 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-type:", t)
print("Content-length:", len(data)) print("Content-length:", len(data))
print('SOAPAction: "%s"' % soapaction) print('SOAPAction: "%s"' % soapaction)


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

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


# SOAPpy modules
# SOAPpy-py3 modules
from .Parser import parseSOAPRPC from .Parser import parseSOAPRPC
from .Config import SOAPConfig from .Config import SOAPConfig
from .Types import faultType, voidType, simplify 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 $' ident = '$Id: NS.py 1468 2008-05-24 01:55:33Z warnes $'
from .version import __version__ 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 null:
if len(cur) or \ 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") raise Error("nils can't have data")


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


if self.zerofloatre.search(s): if self.zerofloatre.search(s):
raise UnderflowError("invalid %s: %s" % (t[1], 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(""" 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 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(...) SOAP.SOAPProxy(...)


use use


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




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

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


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


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

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


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


def date_time_string(self): 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 $' ident = '$Id: Types.py 1496 2010-03-04 23:46:17Z pooryorick $'
from .version import __version__ from .version import __version__
@@ -47,7 +59,7 @@ import re
import time import time
from SOAPpy.Types import * from SOAPpy.Types import *


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


return data return data


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


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


class SOAPException(Exception): class SOAPException(Exception):
def __init__(self, code="", string="", detail=None): 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.code = code
self.string = string self.string = string
self.detail = detail self.detail = detail
@@ -1650,12 +1662,12 @@ class MethodFailed(Exception):
return repr(self.value) 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): 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, This function recursively converts the passed 'container' object,
and all public subobjects. (Private subobjects have names that and all public subobjects. (Private subobjects have names that
@@ -1709,7 +1721,7 @@ def simplify(object, level=0):


def simplify_contents(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 This function recursively converts the sub-objects contained in a
'container' object to simple python types. 'container' object to simple python types.


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

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


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


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


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

@@ -1,5 +1,5 @@
try: try:
import pkg_resources import pkg_resources
__version__ = pkg_resources.get_distribution("SOAPpy").version
__version__ = pkg_resources.get_distribution("SOAPpy-py3").version
except: except:
__version__="xxx" __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 NOTE: The 'testArray' test will fail because 'referenced' elements are
included in the return object. This is a known shortcoming of 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. 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 import os, re,sys


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


from SOAPpy import * from SOAPpy import *


+ 1
- 1
tests/storageTest.py View File

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




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


+ 2
- 2
tests/testClient1.py View File

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


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


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


# gc.set_debug(gc.DEBUG_SAVEALL) # gc.set_debug(gc.DEBUG_SAVEALL)
# for i in range(400): # 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' # s = 'Hello World'
# server.echo(s) # server.echo(s)
# gc.collect() # 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