@@ -319,7 +319,7 @@ usage: onvif [-h] [--host HOST] [--port PORT] [--username USERNAME] [--password
[--cache {all,db,mem,none}] [--health-check-interval HEALTH_CHECK_INTERVAL] [--output OUTPUT] [--version]
[service] [method] [params ...]
-ONVIF Terminal Client — v0.2.8
+ONVIF Terminal Client — v0.2.9
https://github.com/nirsimetri/onvif-python
positional arguments:
@@ -400,7 +400,7 @@ Examples:
```bash
-ONVIF Interactive Shell — v0.2.8
+ONVIF Interactive Shell — v0.2.9
https://github.com/nirsimetri/onvif-python
Basic Commands:
diff --git a/README_ID.md b/README_ID.md
index 5d6e5bd..e3dcb99 100644
--- a/README_ID.md
+++ b/README_ID.md
@@ -3,7 +3,7 @@

-

+

@@ -319,7 +319,7 @@ usage: onvif [-h] [--host HOST] [--port PORT] [--username USERNAME] [--password
[--cache {all,db,mem,none}] [--health-check-interval HEALTH_CHECK_INTERVAL] [--output OUTPUT] [--version]
[service] [method] [params ...]
-ONVIF Terminal Client — v0.2.8
+ONVIF Terminal Client — v0.2.9
https://github.com/nirsimetri/onvif-python
positional arguments:
@@ -401,7 +401,7 @@ Examples:
```bash
-ONVIF Interactive Shell — v0.2.8
+ONVIF Interactive Shell — v0.2.9
https://github.com/nirsimetri/onvif-python
Basic Commands:
diff --git a/onvif/__init__.py b/onvif/__init__.py
index a4e7b3a..1efb484 100644
--- a/onvif/__init__.py
+++ b/onvif/__init__.py
@@ -1,6 +1,6 @@
# onvif/__init__.py
-__version__ = "0.2.8"
+__version__ = "0.2.9"
from .client import ONVIFClient
from .operator import CacheMode
diff --git a/onvif/utils/service.py b/onvif/utils/service.py
index add7632..04e53da 100644
--- a/onvif/utils/service.py
+++ b/onvif/utils/service.py
@@ -8,36 +8,6 @@
logger.addHandler(logging.NullHandler())
-class ONVIFResponse:
- """Transparent wrapper that adds to_dict() to zeep objects."""
-
- def __init__(self, wrapped_object):
- object.__setattr__(self, "_wrapped", wrapped_object)
-
- def __getattr__(self, name):
- return getattr(self._wrapped, name)
-
- def __setattr__(self, name, value):
- if name == "_wrapped":
- object.__setattr__(self, name, value)
- else:
- setattr(self._wrapped, name, value)
-
- def __repr__(self):
- return repr(self._wrapped)
-
- def __str__(self):
- return str(self._wrapped)
-
- def to_dict(self):
- """Convert zeep object to Python dictionary."""
- return (
- {}
- if self._wrapped is None
- else zeep.helpers.serialize_object(self._wrapped)
- )
-
-
def _is_zeep_object(obj):
"""Check if an object is a Zeep-generated object.
@@ -135,7 +105,7 @@ def wrapped_method(*args, **kwargs):
logger.debug(f"Calling wrapped ONVIF method: {name}")
result = attr(*args, **kwargs)
logger.debug(f"ONVIF method {name} completed successfully")
- return ONVIFResponse(result) if result is not None else result
+ return result
except ONVIFOperationException as oe:
# Re-raise ONVIF exceptions as-is
service_name = getattr(self.operator, "service_name", "Unknown")
@@ -149,6 +119,32 @@ def wrapped_method(*args, **kwargs):
return wrapped_method
+ def to_dict(self, zeep_object):
+ """
+ Convert a zeep object (result from ONVIF operation) to Python dictionary.
+
+ Args:
+ zeep_object: The zeep object returned from ONVIF operations
+
+ Returns:
+ dict: Python dictionary representation of the zeep object
+
+ Example:
+ device = client.devicemgmt()
+
+ info = device.GetDeviceInformation()
+ info_dict = device.to_dict(info)
+ print(info_dict)
+
+ profiles = media.GetProfiles()
+ profiles_dict = device.to_dict(profiles)
+ """
+ try:
+ return {} if zeep_object is None else zeep.helpers.serialize_object(zeep_object)
+ except Exception as e:
+ logger.error(f"Failed to convert zeep object to dict: {e}")
+ return {}
+
def type(self, type_name: str):
"""
Create and return an instance of the specified ONVIF type.
diff --git a/pyproject.toml b/pyproject.toml
index 8ef1484..1278563 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "onvif-python"
-version = "0.2.8"
+version = "0.2.9"
description = "A modern Python library for ONVIF-compliant devices"
readme = "README.md"
requires-python = ">=3.9"