0001-start-a-SOAP-common-infrastructure-16104.patch
debian/control | ||
---|---|---|
27 | 27 |
python-lxml, |
28 | 28 |
python-dateutil, |
29 | 29 |
python-pyproj, |
30 |
python-pil |
|
30 |
python-pil, |
|
31 |
python-zeep |
|
31 | 32 |
Recommends: python-soappy, python-phpserialize |
32 | 33 |
Description: Uniform access to multiple data sources and services (Python module) |
33 | 34 |
passerelle/base/models.py | ||
---|---|---|
165 | 165 |
def requests(self): |
166 | 166 |
return passerelle.utils.Request(resource=self, logger=self.logger) |
167 | 167 | |
168 |
def soap_client(self, **kwargs): |
|
169 |
return passerelle.utils.SOAPClient(resource=self, **kwargs) |
|
170 | ||
168 | 171 |
@classmethod |
169 | 172 |
def get_verbose_name(cls): |
170 | 173 |
return cls._meta.verbose_name |
passerelle/utils/__init__.py | ||
---|---|---|
18 | 18 |
from django.views.generic.detail import SingleObjectMixin |
19 | 19 |
from django.contrib.contenttypes.models import ContentType |
20 | 20 |
from django.db import transaction |
21 |
from zeep import Client |
|
22 |
from zeep.cache import InMemoryCache |
|
23 |
from zeep.transports import Transport |
|
21 | 24 | |
22 | 25 |
from passerelle.base.context_processors import template_vars |
23 | 26 |
from passerelle.base.models import ApiUser, AccessRight, BaseResource |
... | ... | |
264 | 267 |
log_function(message, extra=extra) |
265 | 268 | |
266 | 269 | |
270 |
class SOAPClient(Client): |
|
271 |
"""Wrapper around zeep.Client |
|
272 | ||
273 |
resource muste have a wsdl_url and a requests attribute |
|
274 |
""" |
|
275 |
def __init__(self, resource, **kwargs): |
|
276 |
transport = Transport(session=resource.requests, cache=InMemoryCache()) |
|
277 |
super(SOAPClient, self).__init__(resource.wsdl_url, transport=transport, **kwargs) |
|
278 | ||
279 | ||
267 | 280 |
def export_site(): |
268 | 281 |
'''Dump passerelle configuration (users, resources and ACLs) to JSON dumpable dictionnary''' |
269 | 282 |
d = {} |
setup.py | ||
---|---|---|
102 | 102 |
'lxml', |
103 | 103 |
'python-dateutil', |
104 | 104 |
'Pillow', |
105 |
'python-magic' |
|
105 |
'python-magic', |
|
106 |
'zeep' |
|
106 | 107 |
], |
107 | 108 |
cmdclass={ |
108 | 109 |
'build': build, |
tests/data/soap.wsdl | ||
---|---|---|
1 |
<?xml version="1.0"?> |
|
2 |
<definitions |
|
3 |
xmlns:tns="http://example.com/stockquote.wsdl" |
|
4 |
xmlns:xsd1="http://example.com/stockquote.xsd" |
|
5 |
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" |
|
6 |
xmlns="http://schemas.xmlsoap.org/wsdl/" |
|
7 |
name="StockQuote" |
|
8 |
targetNamespace="http://example.com/stockquote.wsdl"> |
|
9 |
<types> |
|
10 |
<schema xmlns="http://www.w3.org/2001/XMLSchema" |
|
11 |
targetNamespace="http://example.com/stockquote.xsd" |
|
12 |
xmlns:tns="http://example.com/stockquote.xsd" > |
|
13 |
<complexType name="Address"> |
|
14 |
<sequence> |
|
15 |
<element minOccurs="0" maxOccurs="1" name="NameFirst" type="string"/> |
|
16 |
<element minOccurs="0" maxOccurs="1" name="NameLast" type="string"/> |
|
17 |
<element minOccurs="0" maxOccurs="1" name="Email" type="string"/> |
|
18 |
</sequence> |
|
19 |
</complexType> |
|
20 |
<complexType name="ArrayOfAddress"> |
|
21 |
<sequence> |
|
22 |
<element name="Address" type="tns:Address" minOccurs="0" maxOccurs="unbounded"/> |
|
23 |
</sequence> |
|
24 |
</complexType> |
|
25 | ||
26 |
<element name="Fault1"> |
|
27 |
<complexType> |
|
28 |
<sequence> |
|
29 |
<element name="message" type="string"/> |
|
30 |
</sequence> |
|
31 |
</complexType> |
|
32 |
</element> |
|
33 |
<element name="Fault2"> |
|
34 |
<complexType> |
|
35 |
<sequence> |
|
36 |
<element name="message" type="string"/> |
|
37 |
</sequence> |
|
38 |
</complexType> |
|
39 |
</element> |
|
40 |
<element name="TradePriceRequest"> |
|
41 |
<complexType> |
|
42 |
<all> |
|
43 |
<element name="tickerSymbol" type="string"/> |
|
44 |
<element name="account" type="tns:account" minOccurs="0" /> |
|
45 |
<element ref="tns:country" minOccurs="0"/> |
|
46 |
</all> |
|
47 |
</complexType> |
|
48 |
</element> |
|
49 |
<element name="TradePrice"> |
|
50 |
<complexType> |
|
51 |
<all> |
|
52 |
<element name="price" type="float"/> |
|
53 |
</all> |
|
54 |
</complexType> |
|
55 |
</element> |
|
56 |
<complexType name="account"> |
|
57 |
<sequence> |
|
58 |
<element name="id" type="int"/> |
|
59 |
<element name="user" type="string"/> |
|
60 |
</sequence> |
|
61 |
</complexType> |
|
62 |
<complexType name="country"> |
|
63 |
<sequence> |
|
64 |
<element name="code" type="string"/> |
|
65 |
</sequence> |
|
66 |
</complexType> |
|
67 |
<element name="country"> |
|
68 |
<complexType> |
|
69 |
<sequence> |
|
70 |
<element name="name" type="string"/> |
|
71 |
<element name="code" type="string"/> |
|
72 |
</sequence> |
|
73 |
</complexType> |
|
74 |
</element> |
|
75 |
</schema> |
|
76 |
</types> |
|
77 |
<message name="GetLastTradePriceInput"> |
|
78 |
<part name="body" element="xsd1:TradePriceRequest"/> |
|
79 |
</message> |
|
80 |
<message name="GetLastTradePriceOutput"> |
|
81 |
<part name="body" element="xsd1:TradePrice"/> |
|
82 |
</message> |
|
83 |
<message name="FaultMessageMsg1"> |
|
84 |
<part name="fault1" element="xsd1:Fault1"/> |
|
85 |
</message> |
|
86 |
<message name="FaultMessageMsg2"> |
|
87 |
<part name="fault2" element="xsd1:Fault2"/> |
|
88 |
</message> |
|
89 |
<portType name="StockQuotePortType"> |
|
90 |
<operation name="GetLastTradePrice"> |
|
91 |
<input message="tns:GetLastTradePriceInput"/> |
|
92 |
<output message="tns:GetLastTradePriceOutput"/> |
|
93 |
<fault message="tns:FaultMessageMsg1" name="fault1"/> |
|
94 |
<fault message="tns:FaultMessageMsg2" name="fault2"/> |
|
95 |
</operation> |
|
96 |
<operation name="GetLastTradePriceNoOutput"> |
|
97 |
<input message="tns:GetLastTradePriceInput"/> |
|
98 |
</operation> |
|
99 |
</portType> |
|
100 |
<binding name="StockQuoteBinding" type="tns:StockQuotePortType"> |
|
101 |
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> |
|
102 |
<operation name="GetLastTradePrice"> |
|
103 |
<soap:operation soapAction="http://example.com/GetLastTradePrice"/> |
|
104 |
<input> |
|
105 |
<soap:body use="literal"/> |
|
106 |
</input> |
|
107 |
<output> |
|
108 |
<soap:body use="literal"/> |
|
109 |
</output> |
|
110 |
<fault name="fault1"> |
|
111 |
<soap:fault name="fault1" use="literal"/> |
|
112 |
</fault> |
|
113 |
<fault name="fault2"> |
|
114 |
<soap:fault name="fault2" use="literal"/> |
|
115 |
</fault> |
|
116 |
</operation> |
|
117 |
<operation name="GetLastTradePriceNoOutput"> |
|
118 |
<soap:operation soapAction="http://example.com/GetLastTradePrice"/> |
|
119 |
<input> |
|
120 |
<soap:body use="literal"/> |
|
121 |
</input> |
|
122 |
</operation> |
|
123 |
</binding> |
|
124 |
<service name="StockQuoteService"> |
|
125 |
<documentation>My first service</documentation> |
|
126 |
<port name="StockQuotePort" binding="tns:StockQuoteBinding"> |
|
127 |
<soap:address location="http://example.com/stockquote"/> |
|
128 |
</port> |
|
129 |
</service> |
|
130 |
</definitions> |
tests/test_soap.py | ||
---|---|---|
1 |
import requests |
|
2 |
from zeep.settings import Settings |
|
3 |
from zeep.plugins import Plugin |
|
4 | ||
5 |
from passerelle.utils import SOAPClient |
|
6 | ||
7 | ||
8 |
WSDL = 'tests/data/soap.wsdl' |
|
9 | ||
10 | ||
11 |
class FooPlugin(Plugin): |
|
12 |
pass |
|
13 | ||
14 | ||
15 |
class BarPlugin(Plugin): |
|
16 |
pass |
|
17 | ||
18 | ||
19 |
class SOAPResource(object): |
|
20 | ||
21 |
def __init__(self): |
|
22 |
self.requests = requests.Session() |
|
23 |
self.wsdl_url = WSDL |
|
24 | ||
25 | ||
26 |
def test_soap_client(): |
|
27 |
soap_resource = SOAPResource() |
|
28 |
settings = Settings(strict=False) |
|
29 |
plugins = [FooPlugin, BarPlugin] |
|
30 |
client = SOAPClient(soap_resource, settings=settings, plugins=plugins) |
|
31 |
assert client.wsdl.location.endswith(WSDL) |
|
32 |
assert client.transport.session == soap_resource.requests |
|
33 |
assert client.transport.cache |
|
34 |
assert client.settings.strict is False |
|
35 |
assert client.plugins == plugins |
|
0 |
- |