Skip to content

Commit a67d02b

Browse files
authored
Lazy caching of WSDL documents (martyanov#6)
1 parent 78f6f38 commit a67d02b

File tree

2 files changed

+62
-1
lines changed

2 files changed

+62
-1
lines changed

aonvif/client.py

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import datetime
2+
import functools
23
import logging
34
import os
45
import typing
@@ -9,6 +10,7 @@
910
import zeep.helpers
1011
import zeep.proxy
1112
import zeep.transports
13+
import zeep.wsdl
1214
import zeep.wsse.username
1315

1416
from . import exceptions
@@ -32,6 +34,18 @@ def wrapped(*args, **kwargs):
3234
return wrapped
3335

3436

37+
@functools.cache
38+
def _get_wsdl_document(path: str):
39+
return zeep.wsdl.Document(
40+
location=path,
41+
transport=zeep.transports.AsyncTransport(cache=MemoryCache()),
42+
settings=zeep.client.Settings(
43+
strict=False,
44+
xml_huge_tree=True,
45+
),
46+
)
47+
48+
3549
class UsernameToken(zeep.wsse.username.UsernameToken):
3650
"""UsernameDigestToken class, with a time drift parameter that can be adjusted.
3751
@@ -140,6 +154,9 @@ def __init__(
140154
use_token_digest: bool = True,
141155
device_time_drift: typing.Optional[datetime.timedelta] = None,
142156
):
157+
if not isinstance(url, str) or not os.path.exists(url):
158+
raise RuntimeError('ONVIFService url must be valid path')
159+
143160
self.url = url
144161
self.xaddr = xaddr
145162

@@ -156,9 +173,12 @@ def __init__(
156173
settings.strict = False
157174
settings.xml_huge_tree = True
158175

176+
# Parse wsdl document
177+
wsdl = _get_wsdl_document(url)
178+
159179
# Create client
160180
self._client = zeep.client.AsyncClient(
161-
wsdl=url,
181+
wsdl=wsdl,
162182
wsse=wsse,
163183
settings=settings,
164184
transport=zeep.transports.AsyncTransport(cache=MemoryCache()),

tests/test_client.py

+41
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import pytest
2+
import zeep
3+
import zeep.wsdl
24

35
import aonvif
46
import aonvif.client
@@ -205,3 +207,42 @@ async def test_client_update_xaddrs_with_custom_capabilities(
205207
'http://www.onvif.org/ver20/imaging/wsdl': 'http://testhost/onvif/imaging_service',
206208
}
207209
mocked_device_mgmt_service.GetCapabilities.assert_not_awaited()
210+
211+
212+
def test_onvif_service_with_invalid_url_type():
213+
with pytest.raises(
214+
aonvif.exceptions.ONVIFError,
215+
match='ONVIFService url must be valid path',
216+
):
217+
aonvif.client.ONVIFService(
218+
xaddr='http://testhost/onvif',
219+
username='test',
220+
password='password',
221+
url=object(),
222+
binding_name='ptz',
223+
)
224+
225+
226+
def test_onvif_service_with_nonexistent_path():
227+
with pytest.raises(
228+
aonvif.exceptions.ONVIFError,
229+
match='ONVIFService url must be valid path',
230+
):
231+
aonvif.client.ONVIFService(
232+
xaddr='http://testhost/onvif',
233+
username='test',
234+
password='password',
235+
url='/tmp/nonexistent/path',
236+
binding_name='ptz',
237+
)
238+
239+
240+
def test_onvif_service_ensure_wsdl_documents_cached():
241+
client1 = aonvif.client.ONVIFCamera('testhost1', 80, 'testuser1', 'password')
242+
service1 = client1.create_devicemgmt_service()
243+
244+
client2 = aonvif.client.ONVIFCamera('testhost2', 80, 'testuser2', 'password')
245+
service2 = client2.create_devicemgmt_service()
246+
247+
assert isinstance(service1._client.wsdl, zeep.wsdl.Document)
248+
assert service1._client.wsdl is service2._client.wsdl

0 commit comments

Comments
 (0)