Skip to content

Commit 42aef07

Browse files
committed
Create zeep.loader and move parser/utils/xsd.utils there
Fixes some duplicate coed
1 parent 2d1d648 commit 42aef07

File tree

6 files changed

+112
-94
lines changed

6 files changed

+112
-94
lines changed

src/zeep/loader.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import os.path
2+
3+
from defusedxml.lxml import fromstring
4+
from lxml import etree
5+
from six.moves.urllib.parse import urljoin, urlparse
6+
7+
from zeep.exceptions import XMLSyntaxError
8+
9+
10+
class ImportResolver(etree.Resolver):
11+
"""Custom lxml resolve to use the transport object"""
12+
def __init__(self, transport):
13+
self.transport = transport
14+
15+
def resolve(self, url, pubid, context):
16+
if urlparse(url).scheme in ('http', 'https'):
17+
content = self.transport.load(url)
18+
return self.resolve_string(content, context)
19+
20+
21+
def parse_xml(content, transport, base_url=None, recover=False):
22+
"""Parse an XML string and return the root Element.
23+
24+
:param content: The XML string
25+
:type content: str
26+
:param transport: The transport instance to load imported documents
27+
:type transport: zeep.transports.Transport
28+
:param base_url: The base url of the document, used to make relative
29+
lookups absolute.
30+
:type base_url: str
31+
:param recover: boolean to indicate if the lxml recover mode should be
32+
enabled. Recover mode tries to parse invalid XML as best as it can.
33+
:type recover: boolean
34+
:returns: The document root
35+
:rtype: lxml.etree._Element
36+
37+
"""
38+
parser = etree.XMLParser(remove_comments=True, resolve_entities=False)
39+
parser.resolvers.add(ImportResolver(transport))
40+
try:
41+
return fromstring(content, parser=parser, base_url=base_url)
42+
except etree.XMLSyntaxError as exc:
43+
raise XMLSyntaxError("Invalid XML content received (%s)" % exc.message)
44+
45+
46+
def load_external(url, transport, base_url=None):
47+
"""Load an external XML document.
48+
49+
:param url:
50+
:param transport:
51+
:param base_url:
52+
53+
"""
54+
if hasattr(url, 'read'):
55+
content = url.read()
56+
else:
57+
if base_url:
58+
url = absolute_location(url, base_url)
59+
content = transport.load(url)
60+
return parse_xml(content, transport, base_url)
61+
62+
63+
def absolute_location(location, base):
64+
"""Make an url absolute (if it is optional) via the passed base url.
65+
66+
:param location: The (relative) url
67+
:type location: str
68+
:param base: The base location
69+
:type base: str
70+
:returns: An absolute URL
71+
:rtype: str
72+
73+
"""
74+
if location == base:
75+
return location
76+
77+
if urlparse(location).scheme in ('http', 'https', 'file'):
78+
return location
79+
80+
if base and urlparse(base).scheme in ('http', 'https', 'file'):
81+
return urljoin(base, location)
82+
else:
83+
if os.path.isabs(location):
84+
return location
85+
if base:
86+
return os.path.realpath(
87+
os.path.join(os.path.dirname(base), location))
88+
return location
89+
90+
91+
def is_relative_path(value):
92+
"""Check if the given value is a relative path
93+
94+
:param value: The value
95+
:type value: str
96+
:returns: Boolean indicating if the url is relative. If it is absolute then
97+
False is returned.
98+
:rtype: boolean
99+
100+
"""
101+
if urlparse(value).scheme in ('http', 'https', 'file'):
102+
return False
103+
return not os.path.isabs(value)

src/zeep/parser.py

Lines changed: 0 additions & 49 deletions
This file was deleted.

src/zeep/wsdl/bindings/soap.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
from zeep import ns, plugins, wsa
77
from zeep.exceptions import Fault, TransportError, XMLSyntaxError
8-
from zeep.parser import parse_xml
9-
from zeep.utils import as_qname, qname_attr, get_media_type
8+
from zeep.loader import parse_xml
9+
from zeep.utils import as_qname, get_media_type, qname_attr
1010
from zeep.wsdl.attachments import MessagePack
1111
from zeep.wsdl.definitions import Binding, Operation
1212
from zeep.wsdl.messages import DocumentMessage, RpcMessage
@@ -145,7 +145,7 @@ def process_reply(self, client, operation, response):
145145
content = response.content
146146

147147
try:
148-
doc = parse_xml(content)
148+
doc = parse_xml(content, self.transport)
149149
except XMLSyntaxError:
150150
raise TransportError(
151151
u'Server returned HTTP status %d (%s)'

src/zeep/wsdl/wsdl.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import six
99
from lxml import etree
1010

11-
from zeep.parser import (
11+
from zeep.loader import (
1212
absolute_location, is_relative_path, load_external, parse_xml)
1313
from zeep.utils import findall_multiple_ns
1414
from zeep.wsdl import parse
@@ -65,7 +65,7 @@ def __init__(self, location, transport, base=None, strict=True):
6565
location=self.location,
6666
strict=self.strict)
6767

68-
document = self._load_content(location)
68+
document = self._get_xml_document(location)
6969

7070
root_definitions = Definition(self, document, self.location)
7171
root_definitions.resolve_imports()
@@ -117,16 +117,14 @@ def dump(self):
117117
print('%s%s' % (' ' * 12, six.text_type(operation)))
118118
print('')
119119

120-
def _load_content(self, location):
120+
def _get_xml_document(self, location):
121121
"""Load the XML content from the given location and return an
122122
lxml.Element object.
123123
124124
:param location: The URL of the document to load
125125
:type location: string
126126
127127
"""
128-
if hasattr(location, 'read'):
129-
return parse_xml(location.read())
130128
return load_external(location, self.transport, self.location)
131129

132130
def _add_definition(self, definition):
@@ -242,7 +240,7 @@ def parse_imports(self, doc):
242240
if key in self.wsdl._definitions:
243241
self.imports[key] = self.wsdl._definitions[key]
244242
else:
245-
document = self.wsdl._load_content(location)
243+
document = self.wsdl._get_xml_document(location)
246244
if etree.QName(document.tag).localname == 'schema':
247245
self.types.add_documents([document], location)
248246
else:

src/zeep/xsd/utils.py

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
1-
from defusedxml.lxml import fromstring
2-
from lxml import etree
3-
41
from six.moves import range
5-
from six.moves.urllib.parse import urlparse
2+
63
from zeep import ns
7-
from zeep.exceptions import XMLSyntaxError
8-
from zeep.parser import absolute_location
94

105

116
class NamePrefixGenerator(object):
@@ -32,34 +27,6 @@ def create_name(self, name):
3227
return name
3328

3429

35-
class ImportResolver(etree.Resolver):
36-
"""Custom lxml resolve to use the transport object"""
37-
def __init__(self, transport):
38-
self.transport = transport
39-
40-
def resolve(self, url, pubid, context):
41-
if urlparse(url).scheme in ('http', 'https'):
42-
content = self.transport.load(url)
43-
return self.resolve_string(content, context)
44-
45-
46-
def parse_xml(content, transport, base_url=None):
47-
parser = etree.XMLParser(remove_comments=True, resolve_entities=False)
48-
parser.resolvers.add(ImportResolver(transport))
49-
try:
50-
return fromstring(content, parser=parser, base_url=base_url)
51-
except etree.XMLSyntaxError as exc:
52-
raise XMLSyntaxError("Invalid XML content received (%s)" % exc.message)
53-
54-
55-
def load_external(url, transport, base_url=None):
56-
if base_url:
57-
url = absolute_location(url, base_url)
58-
59-
response = transport.load(url)
60-
return parse_xml(response, transport, base_url)
61-
62-
6330
def max_occurs_iter(max_occurs, items=None):
6431
assert max_occurs is not None
6532
generator = range(0, max_occurs if max_occurs != 'unbounded' else 2**31-1)

src/zeep/xsd/visitor.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@
66
from lxml import etree
77

88
from zeep.exceptions import XMLParseError
9-
from zeep.parser import absolute_location
9+
from zeep.loader import absolute_location, load_external
1010
from zeep.utils import as_qname, qname_attr
1111
from zeep.xsd import elements as xsd_elements
1212
from zeep.xsd import types as xsd_types
1313
from zeep.xsd.const import xsd_ns
14-
from zeep.xsd.utils import load_external
1514

1615
logger = logging.getLogger(__name__)
1716

0 commit comments

Comments
 (0)