From 9e74bb063e49fb21e9aaa6f8ba583e613b5a3f37 Mon Sep 17 00:00:00 2001 From: Kaburagi <135169292+kaburagisec@users.noreply.github.com> Date: Thu, 22 Oct 2026 02:25:47 +0700 Subject: [PATCH 1/5] style: Run docformatter on onvif module --- onvif/cli/helpers/discovery.py | 6 +- onvif/cli/helpers/execution.py | 3 +- onvif/cli/helpers/files.py | 6 +- onvif/cli/helpers/products.py | 10 +- onvif/cli/helpers/wsdl_parser.py | 24 +- onvif/cli/interactive/reference.py | 9 +- onvif/cli/interactive/service.py | 9 +- onvif/cli/interactive/shell.py | 3 +- onvif/cli/interactive/utils.py | 5 +- onvif/cli/utils.py | 12 +- onvif/client.py | 229 +++++++++--------- onvif/operator.py | 39 ++- onvif/services/accesscontrol.py | 73 +++--- onvif/services/accessrules.py | 29 ++- onvif/services/actionengine.py | 21 +- onvif/services/analytics/analytics.py | 24 +- onvif/services/analytics/ruleengine.py | 12 +- onvif/services/analyticsdevice.py | 34 ++- onvif/services/appmgmt.py | 9 +- onvif/services/authenticationbehavior.py | 58 +++-- onvif/services/credential.py | 73 +++--- onvif/services/deviceio.py | 63 +++-- onvif/services/devicemgmt.py | 223 +++++++++++------ onvif/services/display.py | 26 +- onvif/services/doorcontrol.py | 57 +++-- onvif/services/events/events.py | 18 +- onvif/services/events/notification.py | 6 +- .../services/events/pausable_subscription.py | 16 +- onvif/services/events/pullpoint.py | 12 +- onvif/services/events/subscription.py | 8 +- onvif/services/imaging.py | 25 +- onvif/services/media.py | 227 ++++++++++------- onvif/services/media2.py | 147 +++++++---- onvif/services/ptz.py | 70 ++++-- onvif/services/receiver.py | 25 +- onvif/services/recording.py | 55 +++-- onvif/services/replay.py | 14 +- onvif/services/schedule.py | 46 ++-- onvif/services/search.py | 60 +++-- onvif/services/security/advancedsecurity.py | 3 +- .../services/security/authorizationserver.py | 9 +- onvif/services/security/dot1x.py | 27 ++- onvif/services/security/jwt.py | 6 +- onvif/services/security/keystore.py | 105 +++++--- onvif/services/security/mediasigning.py | 19 +- onvif/services/security/tlsserver.py | 69 +++--- onvif/services/thermal.py | 9 +- onvif/services/uplink.py | 9 +- onvif/utils/discovery.py | 33 +-- onvif/utils/error_handlers.py | 6 +- onvif/utils/exceptions.py | 4 +- onvif/utils/plugins.py | 51 ++-- onvif/utils/service.py | 12 +- onvif/utils/wsdl.py | 31 ++- onvif/utils/zeep.py | 24 +- 55 files changed, 1347 insertions(+), 856 deletions(-) diff --git a/onvif/cli/helpers/discovery.py b/onvif/cli/helpers/discovery.py index 747943a..ec4d19e 100644 --- a/onvif/cli/helpers/discovery.py +++ b/onvif/cli/helpers/discovery.py @@ -14,7 +14,8 @@ def discover_devices( prefer_https: bool = False, filter_term: str | None = None, ) -> list: - """Discover ONVIF devices on the network using WS-Discovery. + """ + Discover ONVIF devices on the network using WS-Discovery. Args: timeout (int): Discovery timeout in seconds @@ -42,7 +43,8 @@ def discover_devices( def select_device_interactive(devices: list) -> tuple[str, int, bool] | None: - """Display devices and allow user to select one interactively. + """ + Display devices and allow user to select one interactively. Args: devices (list): Discovered devices diff --git a/onvif/cli/helpers/execution.py b/onvif/cli/helpers/execution.py index e825e7c..1e8d6dc 100644 --- a/onvif/cli/helpers/execution.py +++ b/onvif/cli/helpers/execution.py @@ -15,7 +15,8 @@ def execute_command( method_name: str, params_str: str | None = None, ) -> Any: - """Execute a single ONVIF command. + """ + Execute a single ONVIF command. Args: client (ONVIFClient): ONVIFClient instance diff --git a/onvif/cli/helpers/files.py b/onvif/cli/helpers/files.py index 042aa07..90b14e0 100644 --- a/onvif/cli/helpers/files.py +++ b/onvif/cli/helpers/files.py @@ -15,7 +15,8 @@ def save_output_to_file( result: Any, output_path: str, debug_mode: bool, client: ONVIFClient ) -> None: - """Save command output to file in appropriate format based on file extension. + """ + Save command output to file in appropriate format based on file extension. Args: result (Any): The ONVIF command result @@ -106,7 +107,8 @@ def save_output_to_file( # pylint: disable=too-many-return-statements,too-many-branches,too-many-nested-blocks def _serialize_for_json(obj: Any) -> Any: - """Recursively serialize ONVIF objects for JSON output. + """ + Recursively serialize ONVIF objects for JSON output. Args: obj: Object to serialize diff --git a/onvif/cli/helpers/products.py b/onvif/cli/helpers/products.py index c5e999b..6820f9b 100644 --- a/onvif/cli/helpers/products.py +++ b/onvif/cli/helpers/products.py @@ -14,8 +14,8 @@ def search_products(search_term: str, page: int = 1, per_page: int = 20) -> None: - """Search ONVIF products database and display results in table format with - pagination. + """ + Search ONVIF products database and display results in table format with pagination. Args: search_term (str): Search term to match against model, post_title, and company_name fields @@ -244,7 +244,7 @@ def _format_date_width(value: str) -> str: def _print_data_header(headers: list[str], col_widths: list[int]) -> None: - """Print table header""" + """Print table header.""" header_line = " | ".join( header.ljust(col_widths[i]) for i, header in enumerate(headers) ) @@ -254,7 +254,7 @@ def _print_data_header(headers: list[str], col_widths: list[int]) -> None: # pylint: disable=too-many-branches,too-many-nested-blocks def _print_data_rows(results: list[Any], col_widths: list[int]) -> None: - """Print data table rows""" + """Print data table rows.""" for row in results: formatted_row = [] for i, value in enumerate(row): @@ -322,7 +322,7 @@ def _print_data_rows(results: list[Any], col_widths: list[int]) -> None: def _print_data_pagination(page: int, total_pages: int) -> None: - """Print pagination information""" + """Print pagination information.""" print() newline = "\n" if total_pages == 1 else "" print(f"{colorize(f'Page {page} of {total_pages}', 'cyan')} {newline}") diff --git a/onvif/cli/helpers/wsdl_parser.py b/onvif/cli/helpers/wsdl_parser.py index 48591c4..2a15cca 100644 --- a/onvif/cli/helpers/wsdl_parser.py +++ b/onvif/cli/helpers/wsdl_parser.py @@ -42,7 +42,8 @@ class OperationTypeInfo(TypedDict): def get_method_documentation( service_obj: Any, method_name: str ) -> dict[str, Any] | None: - """Extracts documentation from WSDL and parameters from the Python method signature. + """ + Extracts documentation from WSDL and parameters from the Python method signature. Returns a dictionary with 'doc', 'required', and 'optional' keys. """ @@ -177,7 +178,8 @@ def get_method_documentation( def get_operation_type_info( service_obj: Any, operation_name: str ) -> OperationTypeInfo | None: - """Extract input and output message types from WSDL for a given operation. + """ + Extract input and output message types from WSDL for a given operation. Returns a dictionary with 'input' and 'output' keys containing message details. """ @@ -250,7 +252,8 @@ def get_operation_type_info( def parse_message_from_wsdl( root, message_name: str, namespaces: dict, schema_context: dict ) -> MessageInfo | None: - """Parse a WSDL message definition to extract parameter details. + """ + Parse a WSDL message definition to extract parameter details. Returns a dictionary with message name and parameters. """ @@ -295,7 +298,8 @@ def parse_message_from_wsdl( def clean_documentation_html(doc_text: str) -> str: - """Clean HTML tags from documentation text and convert links to readable format. + """ + Clean HTML tags from documentation text and convert links to readable format. Args: doc_text: Documentation text that may contain HTML tags @@ -333,7 +337,8 @@ def replace_link(match): def extract_documentation_text(doc_elem) -> str: - """Extract full text from xs:documentation element including child elements. + """ + Extract full text from xs:documentation element including child elements. This handles cases where documentation contains HTML tags like . @@ -457,7 +462,8 @@ def resolve_element_type( depth: int = 0, visited: set[str] | None = None, ) -> list: - """Resolve an element definition from the schema to get its parameters recursively. + """ + Resolve an element definition from the schema to get its parameters recursively. Args: element_name: Name of the element to resolve @@ -620,7 +626,8 @@ def resolve_complex_type( depth: int = 0, visited: set[str] | None = None, ) -> list: - """Resolve a complexType definition to get its child elements. + """ + Resolve a complexType definition to get its child elements. Args: type_name: Name of the complexType to resolve @@ -810,7 +817,8 @@ def parse_inline_complex_type( depth: int = 0, visited: set[str] | None = None, ) -> list: - """Parse an inline complexType element (not referenced by name). + """ + Parse an inline complexType element (not referenced by name). Args: complex_type: The xs:complexType element itself diff --git a/onvif/cli/interactive/reference.py b/onvif/cli/interactive/reference.py index 0828437..e849731 100644 --- a/onvif/cli/interactive/reference.py +++ b/onvif/cli/interactive/reference.py @@ -66,7 +66,8 @@ def do_store(self, line) -> None: def do_show(self, line) -> None: """Show stored data: show or show . or show - [index]""" + [index] + """ if not line: print(colorize("Stored data:", "green")) for name in self.context.stored_data: @@ -91,7 +92,8 @@ def do_show(self, line) -> None: print(f"{colorize('Error:', 'red')} Cannot resolve '{line}'") def _substitute_stored_references(self, params_str: str) -> str: - """Substitute $variable references in parameter string with stored data. + """ + Substitute $variable references in parameter string with stored data. Args: params_str: Parameter string that may contain $variable references @@ -124,7 +126,8 @@ def replace_reference(match) -> Any | str: return re.sub(pattern, replace_reference, params_str) def _resolve_stored_reference(self, reference: str) -> Any | None: - """Resolve stored data reference like 'profiles[0].token' or 'profiles.Token'. + """ + Resolve stored data reference like 'profiles[0].token' or 'profiles.Token'. Args: reference: String reference like 'profiles[0]' or 'profiles.Token' diff --git a/onvif/cli/interactive/service.py b/onvif/cli/interactive/service.py index 1fc425c..104676d 100644 --- a/onvif/cli/interactive/service.py +++ b/onvif/cli/interactive/service.py @@ -93,7 +93,8 @@ def execute_service_method(self, method_name: str, params_str: str) -> None: traceback.print_exc() def do_desc(self, line) -> None: - """Describes a method from its WSDL documentation. + """ + Describes a method from its WSDL documentation. Usage: desc """ @@ -149,7 +150,8 @@ def do_desc(self, line) -> None: # pylint: disable=too-many-branches def do_type(self, line) -> None: - """Show input and output types for a method. + """ + Show input and output types for a method. Usage: type """ @@ -180,7 +182,8 @@ def do_type(self, line) -> None: # Helper function to display parameters recursively with tree-style indentation # pylint: disable=too-many-branches def display_params(params, prefix_lines=None, is_root_level=False): - """Display parameters with tree-style formatting. + """ + Display parameters with tree-style formatting. Args: params: List of parameter dictionaries diff --git a/onvif/cli/interactive/shell.py b/onvif/cli/interactive/shell.py index 390ae67..6eb6d38 100644 --- a/onvif/cli/interactive/shell.py +++ b/onvif/cli/interactive/shell.py @@ -209,7 +209,8 @@ def cmdloop(self, intro=None): def onecmd(self, line): """Override onecmd to handle service method calls without showing cmd.Cmd - traceback.""" + traceback. + """ line = line.strip() if not line: return self.emptyline() diff --git a/onvif/cli/interactive/utils.py b/onvif/cli/interactive/utils.py index bbf2dc1..5aef0f3 100644 --- a/onvif/cli/interactive/utils.py +++ b/onvif/cli/interactive/utils.py @@ -253,8 +253,9 @@ def _handle_connection_error(self) -> None: sys.exit(1) def _split_multi_commands(self, s: str) -> list: - """Split a command string by top-level '&&' separators while ignoring - occurrences inside quotes or bracketed structures. + """ + Split a command string by top-level '&&' separators while ignoring occurrences + inside quotes or bracketed structures. Returns a list of command strings (trimmed). """ diff --git a/onvif/cli/utils.py b/onvif/cli/utils.py index 7dcecca..8f04f97 100644 --- a/onvif/cli/utils.py +++ b/onvif/cli/utils.py @@ -24,7 +24,8 @@ def _is_valid_json(s: str) -> bool: # pylint: disable=too-many-branches def parse_json_params(params_str: str) -> dict[str, Any]: - """Parse parameters from a JSON string or key=value pairs into a dict. + """ + Parse parameters from a JSON string or key=value pairs into a dict. Supports: - JSON: '{"a": 1, "b": 2}' @@ -139,7 +140,8 @@ def split_top_level(s: str): def get_service_required_args(service_name: str) -> list[str] | None: - """Get required arguments for services that need them. + """ + Get required arguments for services that need them. Returns list of required argument names, or None if service doesn't need args. @@ -290,7 +292,8 @@ def format_capabilities_as_services(capabilities) -> str: def format_services_list(services_list: list) -> str: - """Format GetServices response as service list with XAddr and binding support. + """ + Format GetServices response as service list with XAddr and binding support. Shows binding information for all services (single and multi-binding). """ @@ -354,7 +357,8 @@ def format_services_list(services_list: list) -> str: # pylint: disable=too-many-branches def get_device_available_services(client) -> list: - """Get list of services actually available on the connected device. + """ + Get list of services actually available on the connected device. For multi-binding services, returns all available service names. """ diff --git a/onvif/client.py b/onvif/client.py index b624477..d5c5475 100644 --- a/onvif/client.py +++ b/onvif/client.py @@ -65,8 +65,8 @@ def service(func: Callable[P, R]) -> Callable[P, R]: - """Decorator to wrap service accessor methods with `ONVIFOperationException` - handling. + """ + Decorator to wrap service accessor methods with `ONVIFOperationException` handling. This decorator catches any exception raised during service initialization and wraps it in `ONVIFOperationException` for consistent error handling across all @@ -149,7 +149,8 @@ def __init__( wsdl_dir: str | None = None, plugins: list[Plugin] | None = None, ): - """Initialize the ONVIF client. + """ + Initialize the ONVIF client. Args: host (str): Device hostname or IP address @@ -317,7 +318,8 @@ def __init__( def _get_xaddr( # pylint: disable=too-many-branches self, service_name: str, service_path: str ) -> str: - """Resolve XAddr for ONVIF services using a comprehensive 3-tier discovery + """ + Resolve XAddr for ONVIF services using a comprehensive 3-tier discovery approach. 1. GetServices: Try to resolve from GetServices response using namespace mapping @@ -492,10 +494,10 @@ def _configure_plugins( @service def devicemgmt(self) -> Device: """ - - + - Access the Device Management service.""" + Access the Device Management service. + """ if self._devicemgmt is None: logger.debug("Initializing Device Management service") self._devicemgmt = Device(**self.common_args) @@ -564,10 +566,10 @@ def _get_subscription_service( @service def events(self) -> Events: """ - - + - Access the Events service.""" + Access the Events service. + """ if self._events is None: logger.debug("Initializing Events service") self._events = Events( @@ -578,10 +580,10 @@ def events(self) -> Events: @service def pullpoint(self, SubscriptionRef) -> PullPoint: """ - - + - Access the PullPoint service.""" + Access the PullPoint service. + """ logger.debug("Initializing PullPoint service") return self._get_subscription_service( SubscriptionRef, @@ -592,10 +594,10 @@ def pullpoint(self, SubscriptionRef) -> PullPoint: @service def notification(self) -> Notification: """ - - + - Access the Notification service.""" + Access the Notification service. + """ if self._notification is None: logger.debug("Initializing Notification service") self._notification = Notification( @@ -606,10 +608,10 @@ def notification(self) -> Notification: @service def subscription(self, SubscriptionRef) -> Subscription: """ - - + - Access the Subscription service.""" + Access the Subscription service. + """ logger.debug("Initializing Subscription service") return self._get_subscription_service( SubscriptionRef, @@ -620,8 +622,7 @@ def subscription(self, SubscriptionRef) -> Subscription: @service def pausable_subscription(self, SubscriptionRef) -> PausableSubscription: """ - - + Access the PausableSubscription service. """ @@ -637,10 +638,10 @@ def pausable_subscription(self, SubscriptionRef) -> PausableSubscription: @service def imaging(self) -> Imaging: """ - - + - Access the Imaging service.""" + Access the Imaging service. + """ if self._imaging is None: logger.debug("Initializing Imaging service") self._imaging = Imaging( @@ -653,10 +654,10 @@ def imaging(self) -> Imaging: @service def media(self) -> Media: """ - - + - Access the Media service.""" + Access the Media service. + """ if self._media is None: logger.debug("Initializing Media service") self._media = Media( @@ -667,10 +668,10 @@ def media(self) -> Media: @service def media2(self) -> Media2: """ - - + - Access the Media2 service.""" + Access the Media2 service. + """ if self._media2 is None: logger.debug("Initializing Media2 service") self._media2 = Media2( @@ -683,10 +684,10 @@ def media2(self) -> Media2: @service def ptz(self) -> PTZ: """ - - + - Access the PTZ service.""" + Access the PTZ service. + """ if self._ptz is None: logger.debug("Initializing PTZ service") self._ptz = PTZ(xaddr=self._get_xaddr("ptz", "PTZ"), **self.common_args) @@ -697,10 +698,10 @@ def ptz(self) -> PTZ: @service def deviceio(self) -> DeviceIO: """ - - + - Access the DeviceIO service.""" + Access the DeviceIO service. + """ if self._deviceio is None: logger.debug("Initializing DeviceIO service") self._deviceio = DeviceIO( @@ -713,10 +714,10 @@ def deviceio(self) -> DeviceIO: @service def display(self) -> Display: """ - - + - Access the Display service.""" + Access the Display service. + """ if self._display is None: logger.debug("Initializing Display service") self._display = Display( @@ -729,10 +730,10 @@ def display(self) -> Display: @service def analytics(self) -> Analytics: """ - - + - Access the Analytics service.""" + Access the Analytics service. + """ if self._analytics is None: logger.debug("Initializing Analytics service") self._analytics = Analytics( @@ -743,10 +744,10 @@ def analytics(self) -> Analytics: @service def ruleengine(self) -> RuleEngine: """ - - + - Access the RuleEngine service.""" + Access the RuleEngine service. + """ if self._ruleengine is None: logger.debug("Initializing RuleEngine service") self._ruleengine = RuleEngine( @@ -757,10 +758,10 @@ def ruleengine(self) -> RuleEngine: @service def analyticsdevice(self) -> AnalyticsDevice: """ - - + - Access the AnalyticsDevice service.""" + Access the AnalyticsDevice service. + """ if self._analyticsdevice is None: logger.debug("Initializing AnalyticsDevice service") self._analyticsdevice = AnalyticsDevice( @@ -774,10 +775,10 @@ def analyticsdevice(self) -> AnalyticsDevice: @service def accesscontrol(self) -> AccessControl: """ - - + - Access the AccessControl service.""" + Access the AccessControl service. + """ if self._accesscontrol is None: logger.debug("Initializing AccessControl service") self._accesscontrol = AccessControl( @@ -789,10 +790,10 @@ def accesscontrol(self) -> AccessControl: @service def doorcontrol(self) -> DoorControl: """ - - + - Access the DoorControl service.""" + Access the DoorControl service. + """ if self._doorcontrol is None: logger.debug("Initializing DoorControl service") self._doorcontrol = DoorControl( @@ -805,10 +806,10 @@ def doorcontrol(self) -> DoorControl: @service def accessrules(self) -> AccessRules: """ - - + - Access the AccessRules service.""" + Access the AccessRules service. + """ if self._accessrules is None: logger.debug("Initializing AccessRules service") self._accessrules = AccessRules( @@ -821,10 +822,10 @@ def accessrules(self) -> AccessRules: @service def actionengine(self) -> ActionEngine: """ - - + - Access the ActionEngine service.""" + Access the ActionEngine service. + """ if self._actionengine is None: logger.debug("Initializing ActionEngine service") self._actionengine = ActionEngine( @@ -838,10 +839,10 @@ def actionengine(self) -> ActionEngine: @service def appmanagement(self) -> AppManagement: """ - - + - Access the AppManagement service.""" + Access the AppManagement service. + """ if self._appmanagement is None: logger.debug("Initializing AppManagement service") self._appmanagement = AppManagement( @@ -855,10 +856,10 @@ def appmanagement(self) -> AppManagement: @service def authenticationbehavior(self) -> AuthenticationBehavior: """ - - + - Access the AuthenticationBehavior service.""" + Access the AuthenticationBehavior service. + """ if self._authenticationbehavior is None: logger.debug("Initializing AuthenticationBehavior service") self._authenticationbehavior = AuthenticationBehavior( @@ -874,10 +875,10 @@ def authenticationbehavior(self) -> AuthenticationBehavior: @service def credential(self) -> Credential: """ - - + - Access the Credential service.""" + Access the Credential service. + """ if self._credential is None: logger.debug("Initializing Credential service") self._credential = Credential( @@ -891,10 +892,10 @@ def credential(self) -> Credential: @service def recording(self) -> Recording: """ - - + - Access the Recording service.""" + Access the Recording service. + """ if self._recording is None: logger.debug("Initializing Recording service") self._recording = Recording( @@ -908,10 +909,10 @@ def recording(self) -> Recording: @service def replay(self) -> Replay: """ - - + - Access the Replay service.""" + Access the Replay service. + """ if self._replay is None: logger.debug("Initializing Replay service") self._replay = Replay( @@ -925,10 +926,10 @@ def replay(self) -> Replay: @service def provisioning(self) -> Provisioning: """ - - + - Access the Provisioning service.""" + Access the Provisioning service. + """ if self._provisioning is None: logger.debug("Initializing Provisioning service") self._provisioning = Provisioning( @@ -942,10 +943,10 @@ def provisioning(self) -> Provisioning: @service def receiver(self) -> Receiver: """ - - + - Access the Receiver service.""" + Access the Receiver service. + """ if self._receiver is None: logger.debug("Initializing Receiver service") self._receiver = Receiver( @@ -959,10 +960,10 @@ def receiver(self) -> Receiver: @service def schedule(self) -> Schedule: """ - - + - Access the Schedule service.""" + Access the Schedule service. + """ if self._schedule is None: logger.debug("Initializing Schedule service") self._schedule = Schedule( @@ -976,10 +977,10 @@ def schedule(self) -> Schedule: @service def search(self) -> Search: """ - - + - Access the Search service.""" + Access the Search service. + """ if self._search is None: logger.debug("Initializing Search service") self._search = Search( @@ -993,10 +994,10 @@ def search(self) -> Search: @service def thermal(self) -> Thermal: """ - - + - Access the Thermal service.""" + Access the Thermal service. + """ if self._thermal is None: logger.debug("Initializing Thermal service") self._thermal = Thermal( @@ -1010,10 +1011,10 @@ def thermal(self) -> Thermal: @service def uplink(self) -> Uplink: """ - - + - Access the Uplink service.""" + Access the Uplink service. + """ if self._uplink is None: logger.debug("Initializing Uplink service") self._uplink = Uplink( @@ -1027,10 +1028,10 @@ def uplink(self) -> Uplink: @service def security(self) -> AdvancedSecurity: """ - - + - Access the AdvancedSecurity service.""" + Access the AdvancedSecurity service. + """ if self._security is None: logger.debug("Initializing Security service") self._security = AdvancedSecurity( @@ -1042,10 +1043,10 @@ def security(self) -> AdvancedSecurity: @service def jwt(self) -> JWT: """ - - + - Access the JWT service.""" + Access the JWT service. + """ if self._jwt is None: logger.debug("Initializing JWT service") self._jwt = JWT( @@ -1056,10 +1057,10 @@ def jwt(self) -> JWT: @service def keystore(self) -> Keystore: """ - - + - Access the Keystore service.""" + Access the Keystore service. + """ if self._keystore is None: logger.debug("Initializing Keystore service") self._keystore = Keystore( @@ -1070,10 +1071,10 @@ def keystore(self) -> Keystore: @service def tlsserver(self) -> TLSServer: """ - - + - Access the TLSServer service.""" + Access the TLSServer service. + """ if self._tlsserver is None: logger.debug("Initializing TLSServer service") self._tlsserver = TLSServer( @@ -1084,10 +1085,10 @@ def tlsserver(self) -> TLSServer: @service def dot1x(self) -> Dot1X: """ - - + - Access the Dot1X service.""" + Access the Dot1X service. + """ if self._dot1x is None: logger.debug("Initializing Dot1X service") self._dot1x = Dot1X( @@ -1098,10 +1099,10 @@ def dot1x(self) -> Dot1X: @service def authorizationserver(self) -> AuthorizationServer: """ - - + - Access the AuthorizationServer service.""" + Access the AuthorizationServer service. + """ if self._authorizationserver is None: logger.debug("Initializing AuthorizationServer service") self._authorizationserver = AuthorizationServer( @@ -1113,10 +1114,10 @@ def authorizationserver(self) -> AuthorizationServer: @service def mediasigning(self) -> MediaSigning: """ - - + - Access the MediaSigning service.""" + Access the MediaSigning service. + """ if self._mediasigning is None: logger.debug("Initializing MediaSigning service") self._mediasigning = MediaSigning( diff --git a/onvif/operator.py b/onvif/operator.py index 6c9c1b4..7782f9c 100644 --- a/onvif/operator.py +++ b/onvif/operator.py @@ -28,8 +28,7 @@ class CacheMode(Enum): """ - - + WSDL caching strategies for ONVIF client performance optimization. @@ -55,9 +54,8 @@ class CacheMode(Enum): :material-alert-circle:{ .danger } WSDL/XSD documents are fetched without caching - !!! bug "Use case" - Debugging, testing, and situations where fresh WSDL/XSD documents - are required. + !!! bug "Use case" Debugging, testing, and situations where fresh WSDL/XSD + documents are required. """ MEM = "mem" @@ -72,9 +70,8 @@ class CacheMode(Enum): :material-alert-circle:{ .danger } Cache is lost when the process exits - !!! bug "Use case" - Long-running applications, temporary sessions, and applications - where persistent cache storage is not required. + !!! bug "Use case" Long-running applications, temporary sessions, and + applications where persistent cache storage is not required. """ DB = "db" @@ -89,16 +86,14 @@ class CacheMode(Enum): :material-alert-circle:{ .danger } Requires disk I/O and a writable cache directory - !!! bug "Use case" - Production applications, CLI tools, and environments where - WSDL/XSD caching should persist across restarts. + !!! bug "Use case" Production applications, CLI tools, and environments where + WSDL/XSD caching should persist across restarts. """ class ONVIFOperator: """ - - + Low-level ONVIF service operator using Zeep SOAP client. @@ -221,7 +216,8 @@ def _create_session( self, verify_ssl: bool, ) -> Session: - """Create and configure the HTTP session. + """ + Create and configure the HTTP session. Args: verify_ssl: Whether SSL certificates should be verified. @@ -253,7 +249,8 @@ def _create_session( def _create_wsse( self, ) -> UsernameToken | None: - """Create WS-Security authentication configuration. + """ + Create WS-Security authentication configuration. Returns: Zeep WS-Security UsernameToken or None. @@ -274,8 +271,7 @@ def _create_wsse( def call(self, method: str, *args, **kwargs) -> Any: """ - - + Call an ONVIF service operation. @@ -323,8 +319,7 @@ def legacy_call( **kwargs, ) -> Any: """ - - + Call a legacy ONVIF operation using the current WSDL definition. @@ -410,8 +405,7 @@ def legacy_call( def create_type(self, type_name: str) -> Any: """ - - + Create a type instance from WSDL schema for the given type name. @@ -500,7 +494,8 @@ def create_type(self, type_name: str) -> Any: raise AttributeError(f"Type '{type_name}' not found in WSDL schema.") def _initialize_nested_types(self, instance): - """Recursively initialize nested complex types in a Zeep object. + """ + Recursively initialize nested complex types in a Zeep object. This ensures that fields like TimeZone, DateTime, Date, and Time are properly instantiated as objects rather than None values. diff --git a/onvif/services/accesscontrol.py b/onvif/services/accesscontrol.py index 0733a44..c0dbb2c 100644 --- a/onvif/services/accesscontrol.py +++ b/onvif/services/accesscontrol.py @@ -31,14 +31,16 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """This operation returns the capabilities of the access control service. + """ + This operation returns the capabilities of the access control service. A device which provides the access control service shall implement this method. """ return self.operator.call("GetServiceCapabilities") def GetAccessPointInfoList(self, Limit=None, StartReference=None): - """This operation requests a list of all AccessPointInfo items provided by the + """ + This operation requests a list of all AccessPointInfo items provided by the device. A call to this method shall return a StartReference when not all data is @@ -52,7 +54,8 @@ def GetAccessPointInfoList(self, Limit=None, StartReference=None): ) def GetAccessPointInfo(self, Token): - """This operation requests a list of AccessPointInfo items matching the given + """ + This operation requests a list of AccessPointInfo items matching the given tokens. The device shall ignore tokens it cannot resolve and shall return an empty list @@ -63,8 +66,8 @@ def GetAccessPointInfo(self, Token): return self.operator.call("GetAccessPointInfo", Token=Token) def GetAccessPointList(self, Limit=None, StartReference=None): - """This operation requests a list of all AccessPoint items provided by the - device. + """ + This operation requests a list of all AccessPoint items provided by the device. A call to this method shall return a StartReference when not all data is returned and more data is available. The reference shall be valid for retrieving @@ -76,8 +79,8 @@ def GetAccessPointList(self, Limit=None, StartReference=None): ) def GetAccessPoints(self, Token): - """This operation requests a list of AccessPoint items matching the given - tokens. + """ + This operation requests a list of AccessPoint items matching the given tokens. The device shall ignore tokens it cannot resolve and shall return an empty list if there are no items matching the specified tokens. The device shall not return @@ -87,7 +90,8 @@ def GetAccessPoints(self, Token): return self.operator.call("GetAccessPoints", Token=Token) def CreateAccessPoint(self, AccessPoint): - """This operation creates the specified access point in the device. + """ + This operation creates the specified access point in the device. The token field of the AccessPoint structure shall be empty and the device shall allocate a token for the access point. The allocated token shall be returned in @@ -97,8 +101,8 @@ def CreateAccessPoint(self, AccessPoint): return self.operator.call("CreateAccessPoint", AccessPoint=AccessPoint) def SetAccessPoint(self, AccessPoint): - """This method is used to synchronize an access point in a client with the - device. + """ + This method is used to synchronize an access point in a client with the device. If an access point with the specified token does not exist in the device, the access point is created. If an access point with the specified token exists, @@ -111,7 +115,8 @@ def SetAccessPoint(self, AccessPoint): return self.operator.call("SetAccessPoint", AccessPoint=AccessPoint) def ModifyAccessPoint(self, AccessPoint): - """This operation modifies the specified access point. + """ + This operation modifies the specified access point. The token of the access point to modify is specified in the token field of the AccessPoint structure and shall not be empty. All other fields in the structure @@ -122,7 +127,8 @@ def ModifyAccessPoint(self, AccessPoint): return self.operator.call("ModifyAccessPoint", AccessPoint=AccessPoint) def DeleteAccessPoint(self, Token): - """This operation deletes the specified access point. + """ + This operation deletes the specified access point. If it is associated with one or more entities some devices may not be able to delete the access point, and consequently a ReferenceInUse fault shall be @@ -141,11 +147,13 @@ def SetAccessPointAuthenticationProfile(self, Token, AuthenticationProfileToken) def DeleteAccessPointAuthenticationProfile(self, Token): """This operation reverts the authentication behavior for an access point to its - default behavior.""" + default behavior. + """ return self.operator.call("DeleteAccessPointAuthenticationProfile", Token=Token) def GetAreaInfoList(self, Limit=None, StartReference=None): - """This operation requests a list of all AreaInfo items provided by the device. + """ + This operation requests a list of all AreaInfo items provided by the device. A call to this method shall return a StartReference when not all data is returned and more data is available. The reference shall be valid for retrieving @@ -157,7 +165,8 @@ def GetAreaInfoList(self, Limit=None, StartReference=None): ) def GetAreaInfo(self, Token): - """This operation requests a list of AreaInfo items matching the given tokens. + """ + This operation requests a list of AreaInfo items matching the given tokens. The device shall ignore tokens it cannot resolve and shall return an empty list if there are no items matching the specified tokens. The device shall not return @@ -167,7 +176,8 @@ def GetAreaInfo(self, Token): return self.operator.call("GetAreaInfo", Token=Token) def GetAreaList(self, Limit=None, StartReference=None): - """This operation requests a list of all Area items provided by the device. + """ + This operation requests a list of all Area items provided by the device. A call to this method shall return a StartReference when not all data is returned and more data is available. The reference shall be valid for retrieving @@ -179,7 +189,8 @@ def GetAreaList(self, Limit=None, StartReference=None): ) def GetAreas(self, Token): - """This operation requests a list of Area items matching the given tokens. + """ + This operation requests a list of Area items matching the given tokens. The device shall ignore tokens it cannot resolve and shall return an empty list if there are no items matching the specified tokens. The device shall not return @@ -189,7 +200,8 @@ def GetAreas(self, Token): return self.operator.call("GetAreas", Token=Token) def CreateArea(self, Area): - """This operation creates the specified area in the device. + """ + This operation creates the specified area in the device. The token field of the Area structure shall be empty and the device shall allocate a token for the area. The allocated token shall be returned in the @@ -199,7 +211,8 @@ def CreateArea(self, Area): return self.operator.call("CreateArea", Area=Area) def SetArea(self, Area): - """This method is used to synchronize an area in a client with the device. + """ + This method is used to synchronize an area in a client with the device. If an area with the specified token does not exist in the device, the area is created. If an area with the specified token exists, then the area is modified. @@ -212,7 +225,8 @@ def SetArea(self, Area): return self.operator.call("SetArea", Area=Area) def ModifyArea(self, Area): - """This operation modifies the specified area. + """ + This operation modifies the specified area. The token of the area to modify is specified in the token field of the Area structure and shall not be empty. All other fields in the structure shall @@ -222,7 +236,8 @@ def ModifyArea(self, Area): return self.operator.call("ModifyArea", Area=Area) def DeleteArea(self, Token): - """This operation deletes the specified area. + """ + This operation deletes the specified area. If it is associated with one or more entities some devices may not be able to delete the area, and consequently a ReferenceInUse fault shall be generated. If @@ -233,11 +248,13 @@ def DeleteArea(self, Token): def GetAccessPointState(self, Token): """This operation requests the AccessPointState for the access point instance - specified by the token.""" + specified by the token. + """ return self.operator.call("GetAccessPointState", Token=Token) def EnableAccessPoint(self, Token): - """This operation allows enabling an access point. + """ + This operation allows enabling an access point. A device that signals support for DisableAccessPoint capability for a particular access point instance shall implement this command. @@ -245,7 +262,8 @@ def EnableAccessPoint(self, Token): return self.operator.call("EnableAccessPoint", Token=Token) def DisableAccessPoint(self, Token): - """This operation allows disabling an access point. + """ + This operation allows disabling an access point. A device that signals support for the DisableAccessPoint capability for a particular access point instance shall implement this command. @@ -255,8 +273,8 @@ def DisableAccessPoint(self, Token): def Feedback( self, AccessPointToken, FeedbackType, RecognitionType=None, TextMessage=None ): - """This operation controls how the specified access point should indicate - feedback. + """ + This operation controls how the specified access point should indicate feedback. A client can instruct the access point about the door status or that one or more identifiers are needed to grant access, etc. It is typically used in conjunction @@ -281,7 +299,8 @@ def Feedback( def ExternalAuthorization( self, AccessPointToken, Decision, CredentialToken=None, Reason=None ): - """This operation allows to deny or grant decision at an access point instance. + """ + This operation allows to deny or grant decision at an access point instance. A device that signals support for ExternalAuthorization capability for a particular access point instance shall implement this method. diff --git a/onvif/services/accessrules.py b/onvif/services/accessrules.py index f257228..34510b8 100644 --- a/onvif/services/accessrules.py +++ b/onvif/services/accessrules.py @@ -35,7 +35,8 @@ def GetServiceCapabilities(self): return self.operator.call("GetServiceCapabilities") def GetAccessProfileInfo(self, Token): - """This operation requests a list of AccessProfileInfo items matching the given + """ + This operation requests a list of AccessProfileInfo items matching the given tokens. The device shall ignore tokens it cannot resolve and shall return an empty list @@ -46,8 +47,9 @@ def GetAccessProfileInfo(self, Token): return self.operator.call("GetAccessProfileInfo", Token=Token) def GetAccessProfileInfoList(self, Limit=None, StartReference=None): - """This operation requests a list of all of AccessProfileInfo items provided by - the device. + """ + This operation requests a list of all of AccessProfileInfo items provided by the + device. A call to this method shall return a StartReference when not all data is returned and more data is available. The reference shall be valid for retrieving @@ -59,7 +61,8 @@ def GetAccessProfileInfoList(self, Limit=None, StartReference=None): ) def GetAccessProfiles(self, Token): - """This operation returns the specified access profile item matching the given + """ + This operation returns the specified access profile item matching the given tokens. The device shall ignore tokens it cannot resolve and shall return an empty list @@ -70,7 +73,8 @@ def GetAccessProfiles(self, Token): return self.operator.call("GetAccessProfiles", Token=Token) def GetAccessProfileList(self, Limit=None, StartReference=None): - """This operation requests a list of all of access profile items provided by the + """ + This operation requests a list of all of access profile items provided by the device. A call to this method shall return a StartReference when not all data is @@ -83,7 +87,8 @@ def GetAccessProfileList(self, Limit=None, StartReference=None): ) def CreateAccessProfile(self, AccessProfile): - """This operation creates the specified access profile in the device. + """ + This operation creates the specified access profile in the device. The token field of the access profile shall be empty, the service shall allocate a token for the access profile. The allocated token shall be returned in the @@ -95,8 +100,9 @@ def CreateAccessProfile(self, AccessProfile): return self.operator.call("CreateAccessProfile", AccessProfile=AccessProfile) def ModifyAccessProfile(self, AccessProfile): - """This operation will modify the access profile for the specified access - profile token. + """ + This operation will modify the access profile for the specified access profile + token. The token of the access profile to modify is specified in the token field of the AccessProile structure and shall not be empty. All other fields in the structure @@ -108,8 +114,8 @@ def ModifyAccessProfile(self, AccessProfile): return self.operator.call("ModifyAccessProfile", AccessProfile=AccessProfile) def SetAccessProfile(self, AccessProfile): - """This operation will synchronize an access profile in a client with the - device. + """ + This operation will synchronize an access profile in a client with the device. If an access profile with the specified token does not exist in the device, the access profile is created. If an access profile with the specified token exists, @@ -121,7 +127,8 @@ def SetAccessProfile(self, AccessProfile): return self.operator.call("SetAccessProfile", AccessProfile=AccessProfile) def DeleteAccessProfile(self, Token): - """This operation will delete the specified access profile. + """ + This operation will delete the specified access profile. If the access profile is deleted, all access policies associated to the access profile will also be deleted. If it is associated with one or more entities some diff --git a/onvif/services/actionengine.py b/onvif/services/actionengine.py index 8bc60c3..8e40a9f 100644 --- a/onvif/services/actionengine.py +++ b/onvif/services/actionengine.py @@ -35,7 +35,8 @@ def GetServiceCapabilities(self): return self.operator.call("GetServiceCapabilities") def GetSupportedActions(self): - """The service provider returns the supported action types. + """ + The service provider returns the supported action types. The response returns a list of Action Descriptions according to the Action Description Language. @@ -52,7 +53,8 @@ def GetActions(self): return self.operator.call("GetActions") def CreateActions(self, Action): - """The create action operation adds actions to configuration. + """ + The create action operation adds actions to configuration. The create action operation is atomic. If a service provider can not create all of requested actions, the service provider responds with a fault message. @@ -60,7 +62,8 @@ def CreateActions(self, Action): return self.operator.call("CreateActions", Action=Action) def DeleteActions(self, Token): - """The delete operation deletes actions. + """ + The delete operation deletes actions. The delete action operation is atomic. If a service provider can not delete all of requested actions, the service provider responds with a fault message. @@ -68,7 +71,8 @@ def DeleteActions(self, Token): return self.operator.call("DeleteActions", Token=Token) def ModifyActions(self, Action): - """The modify action operation modifies action configurations. + """ + The modify action operation modifies action configurations. The modify action operation is atomic. If a service provider can not modify all of requested action configurations, the service provider responds with a fault @@ -85,7 +89,8 @@ def GetActionTriggers(self): return self.operator.call("GetActionTriggers") def CreateActionTriggers(self, ActionTrigger): - """Creates action triggers. + """ + Creates action triggers. The create action triggers operation is atomic. If a service provider can not create all of requested action triggers, the service provider responds with a @@ -94,7 +99,8 @@ def CreateActionTriggers(self, ActionTrigger): return self.operator.call("CreateActionTriggers", ActionTrigger=ActionTrigger) def DeleteActionTriggers(self, Token): - """Deletes action triggers. + """ + Deletes action triggers. The delete action triggers operation is atomic. If a service provider can not delete all of requested action triggers, the service provider responds with a @@ -103,7 +109,8 @@ def DeleteActionTriggers(self, Token): return self.operator.call("DeleteActionTriggers", Token=Token) def ModifyActionTriggers(self, ActionTrigger): - """Modifies existing action triggers. + """ + Modifies existing action triggers. The modify action triggers operation is atomic. If a service provider can not modify all of requested action trigger configurations, the service provider diff --git a/onvif/services/analytics/analytics.py b/onvif/services/analytics/analytics.py index c545aaa..0397b78 100644 --- a/onvif/services/analytics/analytics.py +++ b/onvif/services/analytics/analytics.py @@ -32,7 +32,8 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the analytics service. + """ + Returns the capabilities of the analytics service. The result is returned in a typed answer. """ @@ -40,13 +41,15 @@ def GetServiceCapabilities(self): def GetSupportedAnalyticsModules(self, ConfigurationToken): """List all analytics modules that are supported by the given - VideoAnalyticsConfiguration.""" + VideoAnalyticsConfiguration. + """ return self.operator.call( "GetSupportedAnalyticsModules", ConfigurationToken=ConfigurationToken ) def CreateAnalyticsModules(self, ConfigurationToken, AnalyticsModule): - """Add one or more analytics modules to an existing VideoAnalyticsConfiguration. + """ + Add one or more analytics modules to an existing VideoAnalyticsConfiguration. The available supported types can be retrieved via GetSupportedAnalyticsModules, where the Name of the supported AnalyticsModules correspond to the type of an @@ -78,7 +81,8 @@ def CreateAnalyticsModules(self, ConfigurationToken, AnalyticsModule): def DeleteAnalyticsModules(self, ConfigurationToken, AnalyticsModuleName): """Remove one or more analytics modules from a VideoAnalyticsConfiguration - referenced by their names.""" + referenced by their names. + """ return self.operator.call( "DeleteAnalyticsModules", ConfigurationToken=ConfigurationToken, @@ -87,14 +91,16 @@ def DeleteAnalyticsModules(self, ConfigurationToken, AnalyticsModuleName): def GetAnalyticsModules(self, ConfigurationToken): """List the currently assigned set of analytics modules of a - VideoAnalyticsConfiguration.""" + VideoAnalyticsConfiguration. + """ return self.operator.call( "GetAnalyticsModules", ConfigurationToken=ConfigurationToken ) def GetAnalyticsModuleOptions(self, ConfigurationToken, Type=None): """Return the options for the supported analytics modules that specify an Option - attribute.""" + attribute. + """ return self.operator.call( "GetAnalyticsModuleOptions", Type=Type, @@ -102,7 +108,8 @@ def GetAnalyticsModuleOptions(self, ConfigurationToken, Type=None): ) def ModifyAnalyticsModules(self, ConfigurationToken, AnalyticsModule): - """Modify the settings of one or more analytics modules of a + """ + Modify the settings of one or more analytics modules of a VideoAnalyticsConfiguration. The modules are referenced by their names. It is allowed to pass only a subset @@ -115,7 +122,8 @@ def ModifyAnalyticsModules(self, ConfigurationToken, AnalyticsModule): ) def GetSupportedMetadata(self, Type=None): - """This method provides a computer readable description of the metadata that the + """ + This method provides a computer readable description of the metadata that the selected analytics modules can generate. The type parameter allows to select a single analytics module. By default the diff --git a/onvif/services/analytics/ruleengine.py b/onvif/services/analytics/ruleengine.py index 9090a7a..108474d 100644 --- a/onvif/services/analytics/ruleengine.py +++ b/onvif/services/analytics/ruleengine.py @@ -32,13 +32,15 @@ def __init__(self, xaddr=None, **kwargs): def GetSupportedRules(self, ConfigurationToken): """List all rules that are supported by the given - VideoAnalyticsConfiguration.""" + VideoAnalyticsConfiguration. + """ return self.operator.call( "GetSupportedRules", ConfigurationToken=ConfigurationToken ) def CreateRules(self, ConfigurationToken, Rule): - """Add one or more rules to an existing VideoAnalyticsConfiguration. + """ + Add one or more rules to an existing VideoAnalyticsConfiguration. The available supported types can be retrieved via GetSupportedRules, where the Name of the supported rule correspond to the type of an rule instance. @@ -66,13 +68,15 @@ def GetRules(self, ConfigurationToken): def GetRuleOptions(self, ConfigurationToken, RuleType=None): """Return the options for the supported rules that specify an Option - attribute.""" + attribute. + """ return self.operator.call( "GetRuleOptions", RuleType=RuleType, ConfigurationToken=ConfigurationToken ) def ModifyRules(self, ConfigurationToken, Rule): - """Modify one or more rules of a VideoAnalyticsConfiguration. + """ + Modify one or more rules of a VideoAnalyticsConfiguration. The rules are referenced by their names. """ diff --git a/onvif/services/analyticsdevice.py b/onvif/services/analyticsdevice.py index 3d2f8a9..7ddbbd8 100644 --- a/onvif/services/analyticsdevice.py +++ b/onvif/services/analyticsdevice.py @@ -33,6 +33,7 @@ class AnalyticsDevice(ONVIFService): | **Operations** | [analyticsdevice.wsdl](https://www.onvif.org/ver10/analyticsdevice.wsdl) | | **Spec** | [Video Analytics Device](https://www.onvif.org/specs/srv/analytics/ONVIF-VideoAnalyticsDevice-Service-Spec-v211.pdf) | """ + # pylint: enable=line-too-long def __init__(self, xaddr=None, **kwargs): @@ -46,7 +47,8 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the analytics device service. + """ + Returns the capabilities of the analytics device service. The result is returned in a typed answer. """ @@ -74,26 +76,30 @@ def SetAnalyticsEngineControl(self, Configuration, ForcePersistence): def GetAnalyticsEngineControl(self, ConfigurationToken): """The GetAnalyticsEngineControl command fetches the analytics engine control if - the analytics engine control token is known.""" + the analytics engine control token is known. + """ return self.operator.call( "GetAnalyticsEngineControl", ConfigurationToken=ConfigurationToken ) def GetAnalyticsEngineControls(self): """This operation lists all available analytics engine controls for the - device.""" + device. + """ return self.operator.call("GetAnalyticsEngineControls") def GetAnalyticsEngine(self, ConfigurationToken): """The GetAnalyticsEngine command fetches the analytics engine configuration if - the token is known.""" + the token is known. + """ return self.operator.call( "GetAnalyticsEngine", ConfigurationToken=ConfigurationToken ) def GetAnalyticsEngines(self): """This operation lists all available analytics engine configurations for the - device.""" + device. + """ return self.operator.call("GetAnalyticsEngines") def SetVideoAnalyticsConfiguration(self, Configuration, ForcePersistence): @@ -114,20 +120,23 @@ def SetAnalyticsEngineInput(self, Configuration, ForcePersistence): def GetAnalyticsEngineInput(self, ConfigurationToken): """The GetAnalyticsEngineInput command fetches the input configuration if the - analytics engine input configuration token is known.""" + analytics engine input configuration token is known. + """ return self.operator.call( "GetAnalyticsEngineInput", ConfigurationToken=ConfigurationToken ) def GetAnalyticsEngineInputs(self): """This operation lists all available analytics engine input configurations for - the device.""" + the device. + """ return self.operator.call("GetAnalyticsEngineInputs") def GetAnalyticsDeviceStreamUri(self, StreamSetup, AnalyticsEngineControlToken): """This operation requests a URI that can be used to initiate a live stream using RTSP as the control protocol if the token of the AnalyticsEngineControl is - known.""" + known. + """ return self.operator.call( "GetAnalyticsDeviceStreamUri", StreamSetup=StreamSetup, @@ -136,7 +145,8 @@ def GetAnalyticsDeviceStreamUri(self, StreamSetup, AnalyticsEngineControlToken): def GetVideoAnalyticsConfiguration(self, ConfigurationToken): """The GetVideoAnalyticsConfiguration command fetches the video analytics - configuration if the video analytics configuration token is known.""" + configuration if the video analytics configuration token is known. + """ return self.operator.call( "GetVideoAnalyticsConfiguration", ConfigurationToken=ConfigurationToken ) @@ -151,14 +161,16 @@ def CreateAnalyticsEngineInputs(self, Configuration, ForcePersistence): def DeleteAnalyticsEngineInputs(self, ConfigurationToken): """This command deletes analytics engine input configurations if the tokens are - known.""" + known. + """ return self.operator.call( "DeleteAnalyticsEngineInputs", ConfigurationToken=ConfigurationToken ) def GetAnalyticsState(self, AnalyticsEngineControlToken): """GetAnalyticsState returns status information of the referenced - AnalyticsEngineControl object.""" + AnalyticsEngineControl object. + """ return self.operator.call( "GetAnalyticsState", AnalyticsEngineControlToken=AnalyticsEngineControlToken ) diff --git a/onvif/services/appmgmt.py b/onvif/services/appmgmt.py index 53a040c..0ef71fd 100644 --- a/onvif/services/appmgmt.py +++ b/onvif/services/appmgmt.py @@ -35,7 +35,8 @@ def GetServiceCapabilities(self): return self.operator.call("GetServiceCapabilities") def Uninstall(self, AppID): - """Removes an app from a device. + """ + Removes an app from a device. This method shall return immedeiately and not wait until the application is completely removed. On completion or failure the method shall generate an @@ -48,7 +49,8 @@ def GetInstalledApps(self): return self.operator.call("GetInstalledApps") def GetAppsInfo(self, AppID=None): - """The caller may provide an application ID to retrieve the information for a + """ + The caller may provide an application ID to retrieve the information for a single application. If no application ID is provided the device shall report the information for all @@ -65,7 +67,8 @@ def Deactivate(self, AppID): return self.operator.call("Deactivate", AppID=AppID) def InstallLicense(self, License, AppID=None): - """Installs a license to the device. + """ + Installs a license to the device. If the device requires PerApp licensing than the AppID parameter shall be provided. diff --git a/onvif/services/authenticationbehavior.py b/onvif/services/authenticationbehavior.py index bc41da7..b6070c7 100644 --- a/onvif/services/authenticationbehavior.py +++ b/onvif/services/authenticationbehavior.py @@ -20,6 +20,7 @@ class AuthenticationBehavior(ONVIFService): | **Operations** | [authenticationbehavior.wsdl](https://www.onvif.org/ver10/authenticationbehavior/wsdl/authenticationbehavior.wsdl) | | **Spec** | [AuthenticationBehavior](https://www.onvif.org/specs/srv/access/ONVIF-AuthenticationBehavior-Service-Spec.pdf) | """ + # pylint: enable=line-too-long def __init__(self, xaddr=None, **kwargs): @@ -34,12 +35,14 @@ def __init__(self, xaddr=None, **kwargs): def GetServiceCapabilities(self): """This operation returns the capabilities of the authentication behavior - service.""" + service. + """ return self.operator.call("GetServiceCapabilities") def GetAuthenticationProfileInfo(self, Token): - """This operation requests a list of AuthenticationProfileInfo items matching - the given tokens. + """ + This operation requests a list of AuthenticationProfileInfo items matching the + given tokens. The device shall ignore tokens it cannot resolve and shall return an empty list if there are no items matching the specified tokens. The device shall not return @@ -48,7 +51,8 @@ def GetAuthenticationProfileInfo(self, Token): return self.operator.call("GetAuthenticationProfileInfo", Token=Token) def GetAuthenticationProfileInfoList(self, Limit=None, StartReference=None): - """This operation requests a list of all of AuthenticationProfileInfo items + """ + This operation requests a list of all of AuthenticationProfileInfo items provided by the device. A call to this method shall return a StartReference when not all data is @@ -63,7 +67,8 @@ def GetAuthenticationProfileInfoList(self, Limit=None, StartReference=None): ) def GetAuthenticationProfiles(self, Token): - """This operation returns the specified AuthenticationProfile item matching the + """ + This operation returns the specified AuthenticationProfile item matching the given tokens. The device shall ignore tokens it cannot resolve and shall return an empty list @@ -73,8 +78,9 @@ def GetAuthenticationProfiles(self, Token): return self.operator.call("GetAuthenticationProfiles", Token=Token) def GetAuthenticationProfileList(self, Limit=None, StartReference=None): - """This operation requests a list of all of AuthenticationProfile items provided - by the device. + """ + This operation requests a list of all of AuthenticationProfile items provided by + the device. A call to this method shall return a StartReference when not all data is returned and more data is available. The reference shall be valid for retrieving @@ -86,7 +92,8 @@ def GetAuthenticationProfileList(self, Limit=None, StartReference=None): ) def CreateAuthenticationProfile(self, AuthenticationProfile): - """This operation creates the specified authentication profile in the device. + """ + This operation creates the specified authentication profile in the device. The token field of the AuthenticationProfile structure shall be empty and the device shall allocate a token for the authentication profile. The allocated @@ -98,7 +105,8 @@ def CreateAuthenticationProfile(self, AuthenticationProfile): ) def SetAuthenticationProfile(self, AuthenticationProfile): - """This method is used to synchronize an authentication profile in a client with + """ + This method is used to synchronize an authentication profile in a client with the device. If an authentication profile with the specified token does not exist in the @@ -114,7 +122,8 @@ def SetAuthenticationProfile(self, AuthenticationProfile): ) def ModifyAuthenticationProfile(self, AuthenticationProfile): - """This operation modifies the specified authentication profile. + """ + This operation modifies the specified authentication profile. The token of the authentication profile to modify is specified in the token field of the AuthenticationProfile structure and shall not be empty. All other @@ -126,7 +135,8 @@ def ModifyAuthenticationProfile(self, AuthenticationProfile): ) def DeleteAuthenticationProfile(self, Token): - """This operation deletes the specified authentication profile. + """ + This operation deletes the specified authentication profile. If the authentication profile is deleted, all authentication policies associated with the authentication profile will also be deleted. If it is associated with @@ -136,7 +146,8 @@ def DeleteAuthenticationProfile(self, Token): return self.operator.call("DeleteAuthenticationProfile", Token=Token) def GetSecurityLevelInfo(self, Token): - """This operation requests a list of SecurityLevelInfo items matching the given + """ + This operation requests a list of SecurityLevelInfo items matching the given tokens. The device shall ignore tokens it cannot resolve and shall return an empty list @@ -146,8 +157,9 @@ def GetSecurityLevelInfo(self, Token): return self.operator.call("GetSecurityLevelInfo", Token=Token) def GetSecurityLevelInfoList(self, Limit=None, StartReference=None): - """This operation requests a list of all of SecurityLevelInfo items provided by - the device. + """ + This operation requests a list of all of SecurityLevelInfo items provided by the + device. A call to this method shall return a StartReference when not all data is returned and more data is available. The reference shall be valid for retrieving @@ -159,7 +171,8 @@ def GetSecurityLevelInfoList(self, Limit=None, StartReference=None): ) def GetSecurityLevels(self, Token): - """This operation returns the specified SecurityLevel item matching the given + """ + This operation returns the specified SecurityLevel item matching the given tokens. The device shall ignore tokens it cannot resolve and shall return an empty list @@ -169,7 +182,8 @@ def GetSecurityLevels(self, Token): return self.operator.call("GetSecurityLevels", Token=Token) def GetSecurityLevelList(self, Limit=None, StartReference=None): - """This operation requests a list of all of SecurityLevel items provided by the + """ + This operation requests a list of all of SecurityLevel items provided by the device. A call to this method shall return a StartReference when not all data is @@ -182,7 +196,8 @@ def GetSecurityLevelList(self, Limit=None, StartReference=None): ) def CreateSecurityLevel(self, SecurityLevel): - """This operation creates the specified security level in the device. + """ + This operation creates the specified security level in the device. The token field of the SecurityLevel structure shall be empty and the device shall allocate a token for the security level. The allocated token shall be @@ -192,7 +207,8 @@ def CreateSecurityLevel(self, SecurityLevel): return self.operator.call("CreateSecurityLevel", SecurityLevel=SecurityLevel) def SetSecurityLevel(self, SecurityLevel): - """This method is used to synchronize an security level in a client with the + """ + This method is used to synchronize an security level in a client with the device. If an security level with the specified token does not exist in the device, the @@ -205,7 +221,8 @@ def SetSecurityLevel(self, SecurityLevel): return self.operator.call("SetSecurityLevel", SecurityLevel=SecurityLevel) def ModifySecurityLevel(self, SecurityLevel): - """This operation modifies the specified security level. + """ + This operation modifies the specified security level. The token of the security level to modify is specified in the token field of the SecurityLevel structure and shall not be empty. All other fields in the @@ -214,7 +231,8 @@ def ModifySecurityLevel(self, SecurityLevel): return self.operator.call("ModifySecurityLevel", SecurityLevel=SecurityLevel) def DeleteSecurityLevel(self, Token): - """This operation deletes the specified security level. + """ + This operation deletes the specified security level. If the security level is deleted, all authentication policies associated with the security level will also be deleted. If it is associated with one or more diff --git a/onvif/services/credential.py b/onvif/services/credential.py index 5613b57..bf0c2f2 100644 --- a/onvif/services/credential.py +++ b/onvif/services/credential.py @@ -36,14 +36,16 @@ def GetServiceCapabilities(self): def GetSupportedFormatTypes(self, CredentialIdentifierTypeName): """This method returns all the supported format types of a specified identifier - type that is supported by the device.""" + type that is supported by the device. + """ return self.operator.call( "GetSupportedFormatTypes", CredentialIdentifierTypeName=CredentialIdentifierTypeName, ) def GetCredentialInfo(self, Token): - """This operation requests a list of CredentialInfo items matching the given + """ + This operation requests a list of CredentialInfo items matching the given tokens. The device shall ignore tokens it cannot resolve and shall return an empty list @@ -54,7 +56,8 @@ def GetCredentialInfo(self, Token): return self.operator.call("GetCredentialInfo", Token=Token) def GetCredentialInfoList(self, Limit=None, StartReference=None): - """This operation requests a list of all CredentialInfo items provided by the + """ + This operation requests a list of all CredentialInfo items provided by the device. A call to this method shall return a StartReference when not all data is @@ -68,8 +71,8 @@ def GetCredentialInfoList(self, Limit=None, StartReference=None): ) def GetCredentials(self, Token): - """This operation returns the specified credential items matching the given - tokens. + """ + This operation returns the specified credential items matching the given tokens. The device shall ignore tokens it cannot resolve and shall return an empty list if there are no items matching specified tokens. The device shall not return a @@ -79,8 +82,8 @@ def GetCredentials(self, Token): return self.operator.call("GetCredentials", Token=Token) def GetCredentialList(self, Limit=None, StartReference=None): - """This operation requests a list of all credential items provided by the - device. + """ + This operation requests a list of all credential items provided by the device. A call to this method shall return a StartReference when not all data is returned and more data is available. The reference shall be valid for retrieving @@ -95,7 +98,8 @@ def GetCredentialList(self, Limit=None, StartReference=None): def CreateCredential( self, Credential, State ): # pylint: disable=redefined-outer-name - """This operation creates a credential. + """ + This operation creates a credential. A call to this method takes a credential structure and a credential state structure as input parameters. The credential state can be created in disabled @@ -110,11 +114,13 @@ def CreateCredential( def SetCredential(self, CredentialData): """This method is used to synchronize a credential in a client with the - device.""" + device. + """ return self.operator.call("SetCredential", CredentialData=CredentialData) def ModifyCredential(self, Credential): # pylint: disable=redefined-outer-name - """This operation modifies the specified credential. + """ + This operation modifies the specified credential. The token of the credential to modify is specified in the token field of the Credential structure and shall not be empty. All other fields in the structure @@ -128,7 +134,8 @@ def ModifyCredential(self, Credential): # pylint: disable=redefined-outer-name return self.operator.call("ModifyCredential", Credential=Credential) def DeleteCredential(self, Token): - """This method deletes the specified credential. + """ + This method deletes the specified credential. If it is associated with one or more entities some devices may not be able to delete the credential, and consequently a ReferenceInUse fault shall be @@ -137,7 +144,8 @@ def DeleteCredential(self, Token): return self.operator.call("DeleteCredential", Token=Token) def GetCredentialState(self, Token): - """This method returns the state for the specified credential. + """ + This method returns the state for the specified credential. If the capability ResetAntipassbackSupported is set to true, then the device shall supply the anti-passback state in the returned credential state structure. @@ -154,7 +162,8 @@ def DisableCredential(self, Token, Reason=None): def ResetAntipassbackViolation(self, CredentialToken): """This method is used to reset anti-passback violations for a specified - credential.""" + credential. + """ return self.operator.call( "ResetAntipassbackViolation", CredentialToken=CredentialToken ) @@ -166,7 +175,8 @@ def GetCredentialIdentifiers(self, CredentialToken): ) def SetCredentialIdentifier(self, CredentialToken, CredentialIdentifier): - """This operation creates or updates a credential identifier for a credential. + """ + This operation creates or updates a credential identifier for a credential. If the type of specified credential identifier already exists, the current credential identifier of that type is replaced. Otherwise the credential @@ -179,7 +189,8 @@ def SetCredentialIdentifier(self, CredentialToken, CredentialIdentifier): ) def DeleteCredentialIdentifier(self, CredentialToken, CredentialIdentifierTypeName): - """This method deletes all the identifier values for the specified type. + """ + This method deletes all the identifier values for the specified type. However, if the identifier type name doesn’t exist in the device, it will be silently ignored without any response. @@ -197,8 +208,8 @@ def GetCredentialAccessProfiles(self, CredentialToken): ) def SetCredentialAccessProfiles(self, CredentialToken, CredentialAccessProfile): - """This operation add or updates the credential access profiles for a - credential. + """ + This operation add or updates the credential access profiles for a credential. The device shall update the credential access profile if the access profile token in the specified credential access profile matches. Otherwise the @@ -211,8 +222,8 @@ def SetCredentialAccessProfiles(self, CredentialToken, CredentialAccessProfile): ) def DeleteCredentialAccessProfiles(self, CredentialToken, AccessProfileToken): - """This method deletes all the credential access profiles for the specified - tokens. + """ + This method deletes all the credential access profiles for the specified tokens. However, if no matching credential access profiles are found, the corresponding access profile tokens are silently ignored without any response. @@ -231,7 +242,8 @@ def GetWhitelist( FormatType=None, Value=None, ): - """This command requests a list of all whitelisted credential identifiers in the + """ + This command requests a list of all whitelisted credential identifiers in the device. A device with capability MaxWhitelistedItems greater than zero, shall implement @@ -247,7 +259,8 @@ def GetWhitelist( ) def AddToWhitelist(self, Identifier): - """This command adds the specified credential identifiers to the whitelist. + """ + This command adds the specified credential identifiers to the whitelist. A device with capability MaxWhitelistedItems greater than zero, shall implement this command. If a specified whitelist item also is blacklisted, the item shall @@ -256,7 +269,8 @@ def AddToWhitelist(self, Identifier): return self.operator.call("AddToWhitelist", Identifier=Identifier) def RemoveFromWhitelist(self, Identifier): - """This command removes the specified credential identifiers from the whitelist. + """ + This command removes the specified credential identifiers from the whitelist. A device with capability MaxWhitelistedItems greater than zero, shall implement this command. This command is idempotent and is safe to repeat even if the @@ -265,7 +279,8 @@ def RemoveFromWhitelist(self, Identifier): return self.operator.call("RemoveFromWhitelist", Identifier=Identifier) def DeleteWhitelist(self): - """This command deletes all credential identifiers from the whitelist. + """ + This command deletes all credential identifiers from the whitelist. A device with capability MaxWhitelistedItems greater than zero, shall implement this command. This command is idempotent and is safe to repeat even if the @@ -281,7 +296,8 @@ def GetBlacklist( FormatType=None, Value=None, ): - """This command requests a list of all blacklisted credential identifiers in the + """ + This command requests a list of all blacklisted credential identifiers in the device. A device with capability MaxBlacklistedItems greater than zero, shall implement @@ -297,7 +313,8 @@ def GetBlacklist( ) def AddToBlacklist(self, Identifier): - """This command adds the specified credential identifiers to the blacklist. + """ + This command adds the specified credential identifiers to the blacklist. A device with capability MaxBlacklistedItems greater than zero, shall implement this command. If a specified blacklist item also is whitelisted, the item shall @@ -306,7 +323,8 @@ def AddToBlacklist(self, Identifier): return self.operator.call("AddToBlacklist", Identifier=Identifier) def RemoveFromBlacklist(self, Identifier): - """This command removes the specified credential identifiers from the blacklist. + """ + This command removes the specified credential identifiers from the blacklist. A device with capability MaxBlacklistedItems greater than zero, shall implement this command. This command is idempotent and is safe to repeat even if the @@ -315,7 +333,8 @@ def RemoveFromBlacklist(self, Identifier): return self.operator.call("RemoveFromBlacklist", Identifier=Identifier) def DeleteBlacklist(self): - """This command deletes all credential identifiers from the blacklist. + """ + This command deletes all credential identifiers from the blacklist. A device with capability MaxBlacklistedItems greater than zero, shall implement this command. This command is idempotent and is safe to repeat even if the diff --git a/onvif/services/deviceio.py b/onvif/services/deviceio.py index 82774f9..117ec4f 100644 --- a/onvif/services/deviceio.py +++ b/onvif/services/deviceio.py @@ -31,14 +31,16 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the device IO service. + """ + Returns the capabilities of the device IO service. The result is returned in a typed answer. """ return self.operator.call("GetServiceCapabilities") def GetRelayOutputOptions(self, RelayOutputToken=None): - """Request the available settings and ranges for one or all relay outputs. + """ + Request the available settings and ranges for one or all relay outputs. A device that has one or more RelayOutputs should support this command. @@ -68,7 +70,8 @@ def GetRelayOutputOptions(self, RelayOutputToken=None): ) def GetAudioSources(self): - """List all available audio sources for the device. + """ + List all available audio sources for the device. The device that has one or more audio sources shall support the listing of available audio inputs through the GetAudioSources command. @@ -76,7 +79,8 @@ def GetAudioSources(self): return self.operator.call("GetAudioSources") def GetAudioOutputs(self): - """List all available audio outputs of a device. + """ + List all available audio outputs of a device. A device that has one or more physical audio outputs shall support listing of available audio outputs through the GetAudioOutputs command. @@ -84,7 +88,8 @@ def GetAudioOutputs(self): return self.operator.call("GetAudioOutputs") def GetVideoSources(self): - """List all available video sources for the device. + """ + List all available video sources for the device. The device that has one or more video inputs shall support the listing of available video sources through the GetVideoSources command. @@ -92,7 +97,8 @@ def GetVideoSources(self): return self.operator.call("GetVideoSources") def GetVideoOutputs(self): - """List all available video outputs of a device. + """ + List all available video outputs of a device. A device that has one or more physical video outputs shall support listing of available video outputs through the GetVideoOutputs command. @@ -100,7 +106,8 @@ def GetVideoOutputs(self): return self.operator.call("GetVideoOutputs") def GetVideoSourceConfiguration(self, VideoSourceToken): - """Get the video source configurations of a VideoSource. + """ + Get the video source configurations of a VideoSource. A device with one or more video sources shall support the GetVideoSourceConfigurations command. @@ -112,7 +119,8 @@ def GetVideoSourceConfiguration(self, VideoSourceToken): ) def GetVideoOutputConfiguration(self, VideoOutputToken): - """Get the configuration of a Video Output. + """ + Get the configuration of a Video Output. A device that has one or more Video Outputs shall support the retrieval of the VideoOutputConfiguration through this command. @@ -122,7 +130,8 @@ def GetVideoOutputConfiguration(self, VideoOutputToken): ) def GetAudioSourceConfiguration(self, AudioSourceToken): - """List the configuration of an Audio Input. + """ + List the configuration of an Audio Input. A device with one or more audio inputs shall support the GetAudioSourceConfiguration command. @@ -134,7 +143,8 @@ def GetAudioSourceConfiguration(self, AudioSourceToken): ) def GetAudioOutputConfiguration(self, AudioOutputToken): - """Request the current configuration of a physical Audio output. + """ + Request the current configuration of a physical Audio output. A device that has one or more AudioOutputs shall support the retrieval of the AudioOutputConfiguration through this command. @@ -146,7 +156,8 @@ def GetAudioOutputConfiguration(self, AudioOutputToken): ) def SetVideoSourceConfiguration(self, Configuration, ForcePersistence): - """Modify a video input configuration. + """ + Modify a video input configuration. A device that has one or more video sources shall support the setting of the VideoSourceConfiguration through this command. @@ -160,7 +171,8 @@ def SetVideoSourceConfiguration(self, Configuration, ForcePersistence): ) def SetVideoOutputConfiguration(self, Configuration, ForcePersistence): - """Modify a video output configuration. + """ + Modify a video output configuration. A device that has one or more video outputs shall support the setting of its video output configuration through this command. @@ -172,7 +184,8 @@ def SetVideoOutputConfiguration(self, Configuration, ForcePersistence): ) def SetAudioSourceConfiguration(self, Configuration, ForcePersistence): - """Modify an audio source configuration. + """ + Modify an audio source configuration. A device that has a one or more audio sources shall support the setting of the AudioSourceConfiguration through this command. @@ -186,7 +199,8 @@ def SetAudioSourceConfiguration(self, Configuration, ForcePersistence): ) def SetAudioOutputConfiguration(self, Configuration, ForcePersistence): - """Modify an audio output configuration. + """ + Modify an audio output configuration. A device that has one or more audio outputs shall support the setting of the AudioOutputConfiguration through this command. @@ -200,7 +214,8 @@ def SetAudioOutputConfiguration(self, Configuration, ForcePersistence): ) def GetVideoSourceConfigurationOptions(self, VideoSourceToken): - """Request the VideoSourceConfigurationOptions of a VideoSource. + """ + Request the VideoSourceConfigurationOptions of a VideoSource. A device with one or more video sources shall support this command. @@ -211,7 +226,8 @@ def GetVideoSourceConfigurationOptions(self, VideoSourceToken): ) def GetVideoOutputConfigurationOptions(self, VideoOutputToken): - """Request the VideoOutputConfigurationOptions of a VideoOutput. + """ + Request the VideoOutputConfigurationOptions of a VideoOutput. A device that has one or more video outputs shall support the retrieval of VideoOutputConfigurationOptions through this command. @@ -221,7 +237,8 @@ def GetVideoOutputConfigurationOptions(self, VideoOutputToken): ) def GetAudioSourceConfigurationOptions(self, AudioSourceToken): - """Request the AudioSourceConfigurationOptions of an AudioSource. + """ + Request the AudioSourceConfigurationOptions of an AudioSource. A device with one or more AudioSources shall support this command. @@ -232,7 +249,8 @@ def GetAudioSourceConfigurationOptions(self, AudioSourceToken): ) def GetAudioOutputConfigurationOptions(self, AudioOutputToken): - """Request the available settings and ranges for a physical Audio output. + """ + Request the available settings and ranges for a physical Audio output. A device that has one or more AudioOutputs shall support this command. @@ -244,11 +262,13 @@ def GetAudioOutputConfigurationOptions(self, AudioOutputToken): def GetRelayOutputs(self): """This operation gets a list of all available relay outputs and their - settings.""" + settings. + """ return self.operator.call("GetRelayOutputs") def SetRelayOutputSettings(self, RelayOutput, RelayOutputToken, Properties): - """This operation sets the settings of a relay output. + """ + This operation sets the settings of a relay output. The relay can work in two relay modes: @@ -320,7 +340,8 @@ def SendReceiveSerialCommand( self, Token=None, SerialData=None, TimeOut=None, DataLength=None, Delimiter=None ): """This operation transmitting arbitrary data to the connected serial device and - then receiving its response data.""" + then receiving its response data. + """ return self.operator.call( "SendReceiveSerialCommand", Token=Token, diff --git a/onvif/services/devicemgmt.py b/onvif/services/devicemgmt.py index 70fc7e8..1217edb 100644 --- a/onvif/services/devicemgmt.py +++ b/onvif/services/devicemgmt.py @@ -32,14 +32,16 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the device service. + """ + Returns the capabilities of the device service. The result is returned in a typed answer. """ return self.operator.call("GetServiceCapabilities") def GetCapabilities(self, Category=None): - """This method has been replaced by the more generic GetServices method. + """ + This method has been replaced by the more generic GetServices method. For capabilities of individual services refer to the GetServiceCapabilities methods. @@ -55,9 +57,9 @@ def GetDeviceInformation(self): return self.operator.call("GetDeviceInformation") def SendAuxiliaryCommand(self, AuxiliaryCommand): - """Manage auxiliary commands supported by a device, such as controlling an - Infrared (IR) lamp, a heater or a wiper or a thermometer that is connected to - the device. + """ + Manage auxiliary commands supported by a device, such as controlling an Infrared + (IR) lamp, a heater or a wiper or a thermometer that is connected to the device. The supported commands can be retrieved via the AuxiliaryCommands capability. @@ -85,7 +87,8 @@ def SendAuxiliaryCommand(self, AuxiliaryCommand): def SetSystemDateAndTime( self, DateTimeType, DaylightSavings, TimeZone=None, UTCDateTime=None ): - """This operation sets the device system date and time. + """ + This operation sets the device system date and time. The device shall support the configuration of the daylight saving setting and of the manual system date and time (if applicable) or indication of NTP time (if @@ -110,7 +113,8 @@ def SetSystemDateAndTime( ) def GetSystemDateAndTime(self): - """This operation gets the device system date and time. + """ + This operation gets the device system date and time. The device shall support the return of the daylight saving setting and of the manual system date and time (if applicable) or indication of NTP time (if @@ -122,13 +126,15 @@ def GetSystemDateAndTime(self): def SetSystemFactoryDefault(self, FactoryDefault): """This operation reloads the parameters on the device to their factory default - values.""" + values. + """ return self.operator.call( "SetSystemFactoryDefault", FactoryDefault=FactoryDefault ) def UpgradeSystemFirmware(self, Firmware): - """This operation upgrades a device firmware version. + """ + This operation upgrades a device firmware version. After a successful upgrade the response message is sent before the device reboots. The device should support firmware upgrade through the @@ -142,7 +148,8 @@ def SystemReboot(self): return self.operator.call("SystemReboot") def RestoreSystem(self, BackupFiles): - """This operation restores the system backup configuration files(s) previously + """ + This operation restores the system backup configuration files(s) previously retrieved from a device. The device should support restore of backup configuration file(s) through the @@ -153,8 +160,8 @@ def RestoreSystem(self, BackupFiles): return self.operator.call("RestoreSystem", BackupFiles=BackupFiles) def GetSystemBackup(self): - """This operation is retrieves system backup configuration file(s) from a - device. + """ + This operation is retrieves system backup configuration file(s) from a device. The device should support return of back up configuration file(s) through the GetSystemBackup command. The backup is returned with reference to a name and @@ -164,7 +171,8 @@ def GetSystemBackup(self): return self.operator.call("GetSystemBackup") def GetSystemLog(self, LogType): - """This operation gets a system log from the device. + """ + This operation gets a system log from the device. The exact format of the system logs is outside the scope of this standard. """ @@ -172,11 +180,13 @@ def GetSystemLog(self, LogType): def GetSystemSupportInformation(self): """This operation gets arbitrary device diagnostics information from the - device.""" + device. + """ return self.operator.call("GetSystemSupportInformation") def GetScopes(self): - """This operation requests the scope parameters of a device. + """ + This operation requests the scope parameters of a device. The scope parameters are used in the device discovery to match a probe message, see Section 7. @@ -196,7 +206,8 @@ def GetScopes(self): return self.operator.call("GetScopes") def SetScopes(self, Scopes): - """This operation sets the scope parameters of a device. + """ + This operation sets the scope parameters of a device. The scope parameters are used in the device discovery to match a probe message. This operation replaces all existing configurable scope parameters (not fixed @@ -207,7 +218,8 @@ def SetScopes(self, Scopes): return self.operator.call("SetScopes", Scopes=Scopes) def AddScopes(self, ScopeItem): - """This operation adds new configurable scope parameters to a device. + """ + This operation adds new configurable scope parameters to a device. The scope parameters are used in the device discovery to match a probe message. The device shall support addition of discovery scope parameters through the @@ -216,7 +228,8 @@ def AddScopes(self, ScopeItem): return self.operator.call("AddScopes", ScopeItem=ScopeItem) def RemoveScopes(self, ScopeItem): - """This operation deletes scope-configurable scope parameters from a device. + """ + This operation deletes scope-configurable scope parameters from a device. The scope parameters are used in the device discovery to match a probe message, see Section 7. The device shall support deletion of discovery scope parameters @@ -225,7 +238,8 @@ def RemoveScopes(self, ScopeItem): return self.operator.call("RemoveScopes", ScopeItem=ScopeItem) def GetDiscoveryMode(self): - """This operation gets the discovery mode of a device. + """ + This operation gets the discovery mode of a device. See Section 7.2 for the definition of the different device discovery modes. The device shall support retrieval of the discovery mode setting through the @@ -234,7 +248,8 @@ def GetDiscoveryMode(self): return self.operator.call("GetDiscoveryMode") def SetDiscoveryMode(self, DiscoveryMode): - """This operation sets the discovery mode operation of a device. + """ + This operation sets the discovery mode operation of a device. See Section 7.2 for the definition of the different device discovery modes. The device shall support configuration of the discovery mode setting through the @@ -243,7 +258,8 @@ def SetDiscoveryMode(self, DiscoveryMode): return self.operator.call("SetDiscoveryMode", DiscoveryMode=DiscoveryMode) def GetRemoteDiscoveryMode(self): - """This operation gets the remote discovery mode of a device. + """ + This operation gets the remote discovery mode of a device. See Section 7.4 for the definition of remote discovery extensions. A device that supports remote discovery shall support retrieval of the remote discovery mode @@ -252,7 +268,8 @@ def GetRemoteDiscoveryMode(self): return self.operator.call("GetRemoteDiscoveryMode") def SetRemoteDiscoveryMode(self, RemoteDiscoveryMode): - """This operation sets the remote discovery mode of operation of a device. + """ + This operation sets the remote discovery mode of operation of a device. See Section 7.4 for the definition of remote discovery remote extensions. A device that supports remote discovery shall support configuration of the @@ -263,7 +280,8 @@ def SetRemoteDiscoveryMode(self, RemoteDiscoveryMode): ) def GetDPAddresses(self): - """This operation gets the remote DP address or addresses from a device. + """ + This operation gets the remote DP address or addresses from a device. If the device supports remote discovery, as specified in Section 7.4, the device shall support retrieval of the remote DP @@ -272,8 +290,9 @@ def GetDPAddresses(self): return self.operator.call("GetDPAddresses") def GetEndpointReference(self): - """A client can ask for the device service endpoint reference address property - that can be used to derive the password equivalent for remote user operation. + """ + A client can ask for the device service endpoint reference address property that + can be used to derive the password equivalent for remote user operation. The device shall support the GetEndpointReference command returning the address property of the device service endpoint reference. @@ -281,7 +300,8 @@ def GetEndpointReference(self): return self.operator.call("GetEndpointReference") def GetRemoteUser(self): - """This operation returns the configured remote user (if any). + """ + This operation returns the configured remote user (if any). A device supporting remote user handling shall support this operation. The user is only valid for the WS-UserToken profile or as an HTTP / RTSP user. @@ -292,7 +312,8 @@ def GetRemoteUser(self): return self.operator.call("GetRemoteUser") def SetRemoteUser(self, RemoteUser=None): - """This operation sets the remote user. + """ + This operation sets the remote user. A device supporting remote user handling shall support this operation. The user is only valid for the WS-UserToken profile @@ -342,7 +363,8 @@ def DeleteUserRole(self, UserRole): return self.operator.call("DeleteUserRole", UserRole=UserRole) def GetUsers(self): - """This operation lists the registered users and corresponding credentials on a + """ + This operation lists the registered users and corresponding credentials on a device. The device shall support retrieval of registered device users and their @@ -351,7 +373,8 @@ def GetUsers(self): return self.operator.call("GetUsers") def CreateUsers(self, User): - """This operation creates new device users and corresponding credentials on a + """ + This operation creates new device users and corresponding credentials on a device for authentication purposes. The device shall support creation of device users and their credentials through @@ -366,7 +389,8 @@ def CreateUsers(self, User): return self.operator.call("CreateUsers", User=User) def DeleteUsers(self, Username): - """This operation deletes users on a device. + """ + This operation deletes users on a device. The device shall support deletion of device users and their credentials through the DeleteUsers command. A device may have one or more fixed users that cannot @@ -376,7 +400,8 @@ def DeleteUsers(self, Username): return self.operator.call("DeleteUsers", Username=Username) def SetUser(self, User): - """This operation updates the settings for one or several users on a device for + """ + This operation updates the settings for one or several users on a device for authentication purposes. The device shall support update of device users and their credentials through @@ -386,7 +411,8 @@ def SetUser(self, User): return self.operator.call("SetUser", User=User) def GetWsdlUrl(self): - """This method allows to provide a URL where product specific WSDL and schema + """ + This method allows to provide a URL where product specific WSDL and schema definitions can be retrieved. This method is deprecated. @@ -395,12 +421,14 @@ def GetWsdlUrl(self): def GetPasswordComplexityOptions(self): """This method allows retrieval of all the available parameters and their valid - ranges for the password complexity configuration.""" + ranges for the password complexity configuration. + """ return self.operator.call("GetPasswordComplexityOptions") def GetPasswordComplexityConfiguration(self): """This method allows retrieval of the current password complexity configuration - settings.""" + settings. + """ return self.operator.call("GetPasswordComplexityConfiguration") def SetPasswordComplexityConfiguration( @@ -425,7 +453,8 @@ def SetPasswordComplexityConfiguration( def GetPasswordHistoryConfiguration(self): """This method allows retrieval of the current password history configuration - settings.""" + settings. + """ return self.operator.call("GetPasswordHistoryConfiguration") def SetPasswordHistoryConfiguration(self, Enabled, Length): @@ -436,19 +465,22 @@ def SetPasswordHistoryConfiguration(self, Enabled, Length): def GetAuthFailureWarningOptions(self): """This method allows retrieval of all the available parameters and their valid - ranges for the authentication failure warning configuration.""" + ranges for the authentication failure warning configuration. + """ return self.operator.call("GetAuthFailureWarningOptions") def GetAuthFailureWarningConfiguration(self): """This method allows retrieval of the current authentication failure warning - configuration settings.""" + configuration settings. + """ return self.operator.call("GetAuthFailureWarningConfiguration") def SetAuthFailureWarningConfiguration( self, Enabled, MonitorPeriod, MaxAuthFailures ): """This method allows setting of the authentication failure warning - configuration.""" + configuration. + """ return self.operator.call( "SetAuthFailureWarningConfiguration", Enabled=Enabled, @@ -458,11 +490,13 @@ def SetAuthFailureWarningConfiguration( def SetHashingAlgorithm(self, Algorithm): """This operation sets the hashing algorithm(s) used in HTTP and RTSP Digest - Authentication.""" + Authentication. + """ return self.operator.call("SetHashingAlgorithm", Algorithm=Algorithm) def SetDPAddresses(self, DPAddress=None): - """This operation sets the remote DP address or addresses on a device. + """ + This operation sets the remote DP address or addresses on a device. If the device supports remote discovery, as specified in Section 7.4, the device shall support configuration of the remote DP @@ -471,7 +505,8 @@ def SetDPAddresses(self, DPAddress=None): return self.operator.call("SetDPAddresses", DPAddress=DPAddress) def GetHostname(self): - """This operation is used by an endpoint to get the hostname from a device. + """ + This operation is used by an endpoint to get the hostname from a device. The device shall return its hostname configurations through the GetHostname command. @@ -479,7 +514,8 @@ def GetHostname(self): return self.operator.call("GetHostname") def SetHostname(self, Name): - """This operation sets the hostname on a device. + """ + This operation sets the hostname on a device. It shall be possible to set the device hostname configurations through the SetHostname command. @@ -491,18 +527,21 @@ def SetHostname(self, Name): def SetHostnameFromDHCP(self, FromDHCP): """This operation controls whether the hostname is set manually or retrieved via - DHCP.""" + DHCP. + """ return self.operator.call("SetHostnameFromDHCP", FromDHCP=FromDHCP) def GetDNS(self): - """This operation gets the DNS settings from a device. + """ + This operation gets the DNS settings from a device. The device shall return its DNS configurations through the GetDNS command. """ return self.operator.call("GetDNS") def SetDNS(self, FromDHCP, SearchDomain=None, DNSManual=None): - """This operation sets the DNS settings on a device. + """ + This operation sets the DNS settings on a device. It shall be possible to set the device DNS configurations through the SetDNS command. @@ -512,7 +551,8 @@ def SetDNS(self, FromDHCP, SearchDomain=None, DNSManual=None): ) def GetNTP(self): - """This operation gets the NTP settings from a device. + """ + This operation gets the NTP settings from a device. If the device supports NTP, it shall be possible to get the NTP server settings through the GetNTP command. @@ -520,7 +560,8 @@ def GetNTP(self): return self.operator.call("GetNTP") def SetNTP(self, FromDHCP, NTPManual=None): - """This operation sets the NTP settings on a device. + """ + This operation sets the NTP settings on a device. If the device supports NTP, it shall be possible to set the NTP server settings through the SetNTP command. @@ -534,7 +575,8 @@ def SetNTP(self, FromDHCP, NTPManual=None): return self.operator.call("SetNTP", FromDHCP=FromDHCP, NTPManual=NTPManual) def GetDynamicDNS(self): - """This operation gets the dynamic DNS settings from a device. + """ + This operation gets the dynamic DNS settings from a device. If the device supports dynamic DNS as specified in [RFC 2136] and [RFC 4702], it shall be possible to get the type, name and TTL through the GetDynamicDNS @@ -543,7 +585,8 @@ def GetDynamicDNS(self): return self.operator.call("GetDynamicDNS") def SetDynamicDNS(self, Type, Name=None, TTL=None): - """This operation sets the dynamic DNS settings on a device. + """ + This operation sets the dynamic DNS settings on a device. If the device supports dynamic DNS as specified in [RFC 2136] and [RFC 4702], it shall be possible to set the type, name and TTL through the SetDynamicDNS @@ -552,7 +595,8 @@ def SetDynamicDNS(self, Type, Name=None, TTL=None): return self.operator.call("SetDynamicDNS", Type=Type, Name=Name, TTL=TTL) def GetNetworkInterfaces(self): - """This operation gets the network interface configuration from a device. + """ + This operation gets the network interface configuration from a device. The device shall support return of network interface configuration settings as defined by the NetworkInterface type through the GetNetworkInterfaces command. @@ -560,7 +604,8 @@ def GetNetworkInterfaces(self): return self.operator.call("GetNetworkInterfaces") def SetNetworkInterfaces(self, InterfaceToken, NetworkInterface): - """This operation sets the network interface configuration on a device. + """ + This operation sets the network interface configuration on a device. The device shall support network configuration of supported network interfaces through the SetNetworkInterfaces command. @@ -576,7 +621,8 @@ def SetNetworkInterfaces(self, InterfaceToken, NetworkInterface): ) def GetNetworkProtocols(self): - """This operation gets defined network protocols from a device. + """ + This operation gets defined network protocols from a device. The device shall support the GetNetworkProtocols command returning configured network protocols. @@ -584,7 +630,8 @@ def GetNetworkProtocols(self): return self.operator.call("GetNetworkProtocols") def SetNetworkProtocols(self, NetworkProtocols): - """This operation configures defined network protocols on a device. + """ + This operation configures defined network protocols on a device. The device shall support configuration of defined network protocols through the SetNetworkProtocols command. @@ -594,7 +641,8 @@ def SetNetworkProtocols(self, NetworkProtocols): ) def GetNetworkDefaultGateway(self): - """This operation gets the default gateway settings from a device. + """ + This operation gets the default gateway settings from a device. The device shall support the GetNetworkDefaultGateway command returning configured default gateway address(es). @@ -602,7 +650,8 @@ def GetNetworkDefaultGateway(self): return self.operator.call("GetNetworkDefaultGateway") def SetNetworkDefaultGateway(self, IPv4Address=None, IPv6Address=None): - """This operation sets the default gateway settings on a device. + """ + This operation sets the default gateway settings on a device. The device shall support configuration of default gateway through the SetNetworkDefaultGateway command. @@ -612,7 +661,8 @@ def SetNetworkDefaultGateway(self, IPv4Address=None, IPv6Address=None): ) def GetZeroConfiguration(self): - """This operation gets the zero-configuration from a device. + """ + This operation gets the zero-configuration from a device. If the device supports dynamic IP configuration according to [RFC3927], it shall support the return of IPv4 zero configuration address and status through the @@ -624,7 +674,8 @@ def GetZeroConfiguration(self): return self.operator.call("GetZeroConfiguration") def SetZeroConfiguration(self, InterfaceToken, Enabled): - """This operation sets the zero-configuration. + """ + This operation sets the zero-configuration. Use GetCapabilities to get if zero-configuration is supported or not. """ @@ -633,7 +684,8 @@ def SetZeroConfiguration(self, InterfaceToken, Enabled): ) def GetIPAddressFilter(self): - """This operation gets the IP address filter settings from a device. + """ + This operation gets the IP address filter settings from a device. If the device supports device access control based on IP filtering rules (denied or accepted ranges of IP addresses), the device shall support the @@ -642,7 +694,8 @@ def GetIPAddressFilter(self): return self.operator.call("GetIPAddressFilter") def SetIPAddressFilter(self, IPAddressFilter): - """This operation sets the IP address filter settings on a device. + """ + This operation sets the IP address filter settings on a device. If the device supports device access control based on IP filtering rules (denied or accepted ranges of IP addresses), the device shall support configuration of @@ -651,7 +704,8 @@ def SetIPAddressFilter(self, IPAddressFilter): return self.operator.call("SetIPAddressFilter", IPAddressFilter=IPAddressFilter) def AddIPAddressFilter(self, IPAddressFilter): - """This operation adds an IP filter address to a device. + """ + This operation adds an IP filter address to a device. If the device supports device access control based on IP filtering rules (denied or accepted ranges of IP addresses), the device shall support adding of IP @@ -660,7 +714,8 @@ def AddIPAddressFilter(self, IPAddressFilter): return self.operator.call("AddIPAddressFilter", IPAddressFilter=IPAddressFilter) def RemoveIPAddressFilter(self, IPAddressFilter): - """This operation deletes an IP filter address from a device. + """ + This operation deletes an IP filter address from a device. If the device supports device access control based on IP filtering rules (denied or accepted ranges of IP addresses), the device shall support deletion of IP @@ -671,7 +726,8 @@ def RemoveIPAddressFilter(self, IPAddressFilter): ) def GetAccessPolicy(self): - """Access to different services and sub-sets of services should be subject to + """ + Access to different services and sub-sets of services should be subject to access control. The WS-Security framework gives the prerequisite for end-point authentication. @@ -686,7 +742,8 @@ def GetAccessPolicy(self): return self.operator.call("GetAccessPolicy") def SetAccessPolicy(self, PolicyFile): - """This command sets the device access security policy (for more details on the + """ + This command sets the device access security policy (for more details on the access security policy see the Get command). If the device supports access policy settings based on WS- Security @@ -767,14 +824,16 @@ def LoadCACertificates(self, CACertificate): return self.operator.call("LoadCACertificates", CACertificate=CACertificate) def GetRelayOutputs(self): - """This operation gets a list of all available relay outputs and their settings. + """ + This operation gets a list of all available relay outputs and their settings. This method has been deprecated with version 2.0. Refer to the DeviceIO service. """ return self.operator.call("GetRelayOutputs") def SetRelayOutputSettings(self, RelayOutputToken, Properties): - """This operation sets the settings of a relay output. + """ + This operation sets the settings of a relay output. This method has been deprecated with version 2.0. Refer to the DeviceIO service. """ @@ -785,7 +844,8 @@ def SetRelayOutputSettings(self, RelayOutputToken, Properties): ) def SetRelayOutputState(self, RelayOutputToken, LogicalState): - """This operation sets the state of a relay output. + """ + This operation sets the state of a relay output. This method has been deprecated with version 2.0. Refer to the DeviceIO service. """ @@ -824,22 +884,24 @@ def DeleteDot1XConfiguration(self, Dot1XConfigurationToken=None): ) def GetDot11Capabilities(self): - """This operation returns the IEEE802.11 capabilities. + """ + This operation returns the IEEE802.11 capabilities. The device shall support this operation. """ return self.operator.call("GetDot11Capabilities") def GetDot11Status(self, InterfaceToken): - """This operation returns the status of a wireless network interface. + """ + This operation returns the status of a wireless network interface. The device shall support this command. """ return self.operator.call("GetDot11Status", InterfaceToken=InterfaceToken) def ScanAvailableDot11Networks(self, InterfaceToken): - """This operation returns a lists of the wireless networks in range of the - device. + """ + This operation returns a lists of the wireless networks in range of the device. A device should support this operation. """ @@ -848,7 +910,8 @@ def ScanAvailableDot11Networks(self, InterfaceToken): ) def GetSystemUris(self): - """This operation is used to retrieve URIs from which system information may be + """ + This operation is used to retrieve URIs from which system information may be downloaded using HTTP. URIs may be returned for the following system information: @@ -869,7 +932,8 @@ def GetSystemUris(self): return self.operator.call("GetSystemUris") def StartFirmwareUpgrade(self): - """This operation initiates a firmware upgrade using the HTTP POST mechanism. + """ + This operation initiates a firmware upgrade using the HTTP POST mechanism. The response to the command includes an HTTP URL to which the upgrade file may be uploaded. The actual upgrade takes place as soon as the HTTP POST operation @@ -918,7 +982,8 @@ def UpgradeFirmware(self, Version): return self.operator.call("UpgradeFirmware", Version=Version) def StartSystemRestore(self): - """This operation initiates a system restore from backed up configuration data + """ + This operation initiates a system restore from backed up configuration data using the HTTP POST mechanism. The response to the command includes an HTTP URL to which the backup file may be @@ -949,7 +1014,8 @@ def GetStorageConfigurations(self): return self.operator.call("GetStorageConfigurations") def CreateStorageConfiguration(self, StorageConfiguration): - """This operation creates a new storage configuration. + """ + This operation creates a new storage configuration. The configuration data shall be created in the device and shall be persistent (remain after reboot). @@ -960,7 +1026,8 @@ def CreateStorageConfiguration(self, StorageConfiguration): def GetStorageConfiguration(self, Token): """This operation retrieves the Storage configuration associated with the given - storage configuration token.""" + storage configuration token. + """ return self.operator.call("GetStorageConfiguration", Token=Token) def SetStorageConfiguration(self, StorageConfiguration): @@ -971,12 +1038,14 @@ def SetStorageConfiguration(self, StorageConfiguration): def DeleteStorageConfiguration(self, Token): """This operation deletes the given storage configuration and configuration - change shall always be persistent.""" + change shall always be persistent. + """ return self.operator.call("DeleteStorageConfiguration", Token=Token) def GetGeoLocation(self): """This operation lists all existing geo location configurations for the - device.""" + device. + """ return self.operator.call("GetGeoLocation") def SetGeoLocation(self, Location): diff --git a/onvif/services/display.py b/onvif/services/display.py index 1abfe5c..b8cf1c2 100644 --- a/onvif/services/display.py +++ b/onvif/services/display.py @@ -31,14 +31,16 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the display service. + """ + Returns the capabilities of the display service. The result is returned in a typed answer. """ return self.operator.call("GetServiceCapabilities") def GetLayout(self, VideoOutput): - """Return the current layout of a video output. + """ + Return the current layout of a video output. The Layout assigns a pane configuration to a certain area of the display. The layout settings directly affect a specific video output. The layout consists of @@ -47,7 +49,8 @@ def GetLayout(self, VideoOutput): return self.operator.call("GetLayout", VideoOutput=VideoOutput) def SetLayout(self, VideoOutput, Layout): - """Change the layout of a display (e.g. change from single view to split screen + """ + Change the layout of a display (e.g. change from single view to split screen view).The Layout assigns a pane configuration to a certain area of the display. The layout settings directly affect a specific video output. The layout consists @@ -60,7 +63,8 @@ def SetLayout(self, VideoOutput, Layout): return self.operator.call("SetLayout", VideoOutput=VideoOutput, Layout=Layout) def GetDisplayOptions(self, VideoOutput): - """The Display Options contain the supported layouts (LayoutOptions) and the + """ + The Display Options contain the supported layouts (LayoutOptions) and the decoding and encoding capabilities (CodingCapabilities) of the device. The GetDisplayOptions command returns both, Layout and Coding Capabilities, of a @@ -69,7 +73,8 @@ def GetDisplayOptions(self, VideoOutput): return self.operator.call("GetDisplayOptions", VideoOutput=VideoOutput) def GetPaneConfigurations(self, VideoOutput): - """List all currently defined panes of a device for a specified video output + """ + List all currently defined panes of a device for a specified video output (regardless if this pane is visible at a moment). A Pane is a display area on the monitor that is attached to a video output. A @@ -87,7 +92,8 @@ def GetPaneConfiguration(self, VideoOutput, Pane): ) def SetPaneConfigurations(self, VideoOutput, PaneConfiguration): - """Modify one or more configurations of the specified video output. + """ + Modify one or more configurations of the specified video output. This method will only modify the provided configurations and leave the others unchanged. Use DeletePaneConfiguration to remove pane configurations. @@ -107,8 +113,9 @@ def SetPaneConfiguration(self, VideoOutput, PaneConfiguration): ) def CreatePaneConfiguration(self, VideoOutput, PaneConfiguration): - """Create a new pane configuration describing the streaming and coding settings - for a display area. + """ + Create a new pane configuration describing the streaming and coding settings for + a display area. This optional method is only supported by devices that signal support of dynamic pane creation via their capabilities. @@ -122,7 +129,8 @@ def CreatePaneConfiguration(self, VideoOutput, PaneConfiguration): ) def DeletePaneConfiguration(self, VideoOutput, PaneToken): - """Delete a pane configuration. + """ + Delete a pane configuration. A service must respond with an error if the pane configuration is in use by the current layout. diff --git a/onvif/services/doorcontrol.py b/onvif/services/doorcontrol.py index f9ee081..80c8c05 100644 --- a/onvif/services/doorcontrol.py +++ b/onvif/services/doorcontrol.py @@ -31,7 +31,8 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """This operation returns the capabilities of the service. + """ + This operation returns the capabilities of the service. An ONVIF compliant device which provides the Door Control service shall implement this method. @@ -39,7 +40,8 @@ def GetServiceCapabilities(self): return self.operator.call("GetServiceCapabilities") def GetDoorInfoList(self, Limit=None, StartReference=None): - """This operation requests a list of all DoorInfo items provided by the device. + """ + This operation requests a list of all DoorInfo items provided by the device. An ONVIF compliant device that provides Door Control service shall implement this method. A call to this method shall return a StartReference when not all @@ -52,7 +54,8 @@ def GetDoorInfoList(self, Limit=None, StartReference=None): ) def GetDoorInfo(self, Token): - """This operation requests a list of DoorInfo items matching the given tokens. + """ + This operation requests a list of DoorInfo items matching the given tokens. An ONVIF-compliant device that provides Door Control service shall implement this method. The device shall ignore tokens it cannot resolve and shall return @@ -63,7 +66,8 @@ def GetDoorInfo(self, Token): return self.operator.call("GetDoorInfo", Token=Token) def GetDoorList(self, Limit=None, StartReference=None): - """This operation requests a list of all Door items provided by the device. + """ + This operation requests a list of all Door items provided by the device. A call to this method shall return a StartReference when not all data is returned and more data is available. The reference shall be valid for retrieving @@ -76,7 +80,8 @@ def GetDoorList(self, Limit=None, StartReference=None): ) def GetDoors(self, Token): - """This operation requests a list of Door items matching the given tokens. + """ + This operation requests a list of Door items matching the given tokens. The device shall ignore tokens it cannot resolve and shall return an empty list if there are no items matching specified tokens. The device shall not return a @@ -86,7 +91,8 @@ def GetDoors(self, Token): return self.operator.call("GetDoors", Token=Token) def CreateDoor(self, Door): - """This operation creates the specified door in the device. + """ + This operation creates the specified door in the device. The token field of the Door structure shall be empty and the device shall allocate a token for the door. The allocated token shall be returned in the @@ -96,7 +102,8 @@ def CreateDoor(self, Door): return self.operator.call("CreateDoor", Door=Door) def SetDoor(self, Door): - """This method is used to synchronize a door in a client with the device. + """ + This method is used to synchronize a door in a client with the device. If a door with the specified token does not exist in the device, the door is created. If a door with the specified token exists, then the door is modified. A @@ -109,7 +116,8 @@ def SetDoor(self, Door): return self.operator.call("SetDoor", Door=Door) def ModifyDoor(self, Door): - """This operation modifies the specified door. + """ + This operation modifies the specified door. The token of the door to modify is specified in the token field of the Door structure and shall not be empty. All other fields in the structure shall @@ -119,7 +127,8 @@ def ModifyDoor(self, Door): return self.operator.call("ModifyDoor", Door=Door) def DeleteDoor(self, Token): - """This operation deletes the specified door. + """ + This operation deletes the specified door. If it is associated with one or more entities some devices may not be able to delete the door, and consequently a ReferenceInUse fault shall be generated. If @@ -129,7 +138,8 @@ def DeleteDoor(self, Token): return self.operator.call("DeleteDoor", Token=Token) def GetDoorState(self, Token): - """This operation requests the state of a Door specified by the Token. + """ + This operation requests the state of a Door specified by the Token. A device implementing the Door Control service shall be capable of reporting the status of a door using a DoorState structure available from the GetDoorState @@ -146,7 +156,8 @@ def AccessDoor( PreAlarmTime=None, Extension=None, ): - """This operation allows momentarily accessing a Door. + """ + This operation allows momentarily accessing a Door. It invokes the functionality typically used when a card holder presents a card to a card reader at the door and is granted access. The DoorMode shall change to @@ -174,7 +185,8 @@ def AccessDoor( ) def LockDoor(self, Token): - """This operation allows locking a Door. + """ + This operation allows locking a Door. The DoorMode shall change to Locked state. Please refer to Locked mode in section [DoorMode] for more details. A device that signals support for Lock @@ -185,7 +197,8 @@ def LockDoor(self, Token): return self.operator.call("LockDoor", Token=Token) def UnlockDoor(self, Token): - """This operation allows unlocking a Door. + """ + This operation allows unlocking a Door. The DoorMode shall change to Unlocked state. Please refer to Unlocked mode in section [DoorMode] for more details. A device that signals support for Unlock @@ -196,7 +209,8 @@ def UnlockDoor(self, Token): return self.operator.call("UnlockDoor", Token=Token) def BlockDoor(self, Token): - """This operation allows blocking a Door and preventing momentary access + """ + This operation allows blocking a Door and preventing momentary access (AccessDoor command). The DoorMode shall change to Blocked state. Please refer to Blocked mode in @@ -208,7 +222,8 @@ def BlockDoor(self, Token): return self.operator.call("BlockDoor", Token=Token) def LockDownDoor(self, Token): - """This operation allows locking and preventing other actions until a + """ + This operation allows locking and preventing other actions until a LockDownRelease command is invoked. The DoorMode shall change to LockedDown state. Please refer to LockedDown mode @@ -223,7 +238,8 @@ def LockDownDoor(self, Token): return self.operator.call("LockDownDoor", Token=Token) def LockDownReleaseDoor(self, Token): - """This operation allows releasing the LockedDown state of a Door. + """ + This operation allows releasing the LockedDown state of a Door. The DoorMode shall change back to its previous/next state. It is not defined what the previous/next state shall be, but typically - Locked. This method shall @@ -232,7 +248,8 @@ def LockDownReleaseDoor(self, Token): return self.operator.call("LockDownReleaseDoor", Token=Token) def LockOpenDoor(self, Token): - """This operation allows unlocking a Door and preventing other actions until + """ + This operation allows unlocking a Door and preventing other actions until LockOpenRelease method is invoked. The DoorMode shall change to LockedOpen state. Please refer to LockedOpen mode @@ -246,7 +263,8 @@ def LockOpenDoor(self, Token): return self.operator.call("LockOpenDoor", Token=Token) def LockOpenReleaseDoor(self, Token): - """This operation allows releasing the LockedOpen state of a Door. + """ + This operation allows releasing the LockedOpen state of a Door. The DoorMode shall change state from the LockedOpen state back to its previous/next state. It is not defined what the previous/next state shall be, @@ -257,7 +275,8 @@ def LockOpenReleaseDoor(self, Token): return self.operator.call("LockOpenReleaseDoor", Token=Token) def DoubleLockDoor(self, Token): - """This operation is used for securely locking a Door. + """ + This operation is used for securely locking a Door. A call to this method shall change DoorMode state to DoubleLocked. Please refer to DoubleLocked mode in section [DoorMode] for more details. A device that diff --git a/onvif/services/events/events.py b/onvif/services/events/events.py index a6f5594..df11dd8 100644 --- a/onvif/services/events/events.py +++ b/onvif/services/events/events.py @@ -32,7 +32,8 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the event service. + """ + Returns the capabilities of the event service. The result is returned in a typed answer. """ @@ -41,7 +42,8 @@ def GetServiceCapabilities(self): def CreatePullPointSubscription( self, Filter=None, InitialTerminationTime=None, SubscriptionPolicy=None ): - """This method returns a PullPointSubscription that can be polled using + """ + This method returns a PullPointSubscription that can be polled using PullMessages. This message contains the same elements as the SubscriptionRequest of the WS- @@ -60,7 +62,8 @@ def CreatePullPointSubscription( ) def GetEventProperties(self): - """The WS-BaseNotification specification defines a set of OPTIONAL WS- + """ + The WS-BaseNotification specification defines a set of OPTIONAL WS- ResouceProperties. This specification does not require the implementation of the WS- @@ -71,7 +74,8 @@ def GetEventProperties(self): return self.operator.call("GetEventProperties") def AddEventBroker(self, EventBroker): - """The AddEventBroker command allows an ONVIF client to add an event broker + """ + The AddEventBroker command allows an ONVIF client to add an event broker configuration to device to enable ONVIF events to be transferred to an event broker. @@ -82,10 +86,12 @@ def AddEventBroker(self, EventBroker): def DeleteEventBroker(self, Address): """The DeleteEventBroker allows an ONVIF client to delete an event broker - configuration from an ONVIF device.""" + configuration from an ONVIF device. + """ return self.operator.call("DeleteEventBroker", Address=Address) def GetEventBrokers(self, Address=None): """The GetEventBrokers command lets a client retrieve event broker - configurations from the device.""" + configurations from the device. + """ return self.operator.call("GetEventBrokers", Address=Address) diff --git a/onvif/services/events/notification.py b/onvif/services/events/notification.py index 8e033ac..7e2efdc 100644 --- a/onvif/services/events/notification.py +++ b/onvif/services/events/notification.py @@ -38,7 +38,8 @@ def Subscribe( InitialTerminationTime=None, SubscriptionPolicy=None, ): - """Create a subscription for receiving event notifications. + """ + Create a subscription for receiving event notifications. Registers a notification consumer with the NotificationProducer. Event notifications matching the optional filter are delivered to the consumer @@ -53,7 +54,8 @@ def Subscribe( ) def GetCurrentMessage(self, Topic): - """Retrieve the current message for a notification topic. + """ + Retrieve the current message for a notification topic. Requests the current state message associated with the specified topic from the NotificationProducer. diff --git a/onvif/services/events/pausable_subscription.py b/onvif/services/events/pausable_subscription.py index f000ae5..b49b45f 100644 --- a/onvif/services/events/pausable_subscription.py +++ b/onvif/services/events/pausable_subscription.py @@ -35,8 +35,9 @@ def __init__(self, xaddr=None, **kwargs): ) def Renew(self, TerminationTime=None): - """An ONVIF compliant device shall support this command if it signals support - for [WS-Base Notification] via the MaxNotificationProducers capability. + """ + An ONVIF compliant device shall support this command if it signals support for + [WS-Base Notification] via the MaxNotificationProducers capability. The command shall at least support a Timeout of one minute. A device shall respond with both parameters CurrentTime and TerminationTime as utc using the @@ -45,7 +46,8 @@ def Renew(self, TerminationTime=None): return self.operator.call("Renew", TerminationTime=TerminationTime) def Unsubscribe(self): - """The device shall provide the following Unsubscribe command for all + """ + The device shall provide the following Unsubscribe command for all SubscriptionManager endpoints returned by the CreatePullPointSubscription command. @@ -57,10 +59,11 @@ def Unsubscribe(self): return self.operator.call("Unsubscribe") def PauseSubscription(self): - """Temporarily suspend notification delivery for the subscription. + """ + Temporarily suspend notification delivery for the subscription. Successfully processing this request places the subscription in a paused - state. Notifications can be resumed by calling ResumeSubscription(). + state. Notifications can be resumed by calling ResumeSubscription. Note: Notifications may continue to be produced while the pause request is @@ -69,7 +72,8 @@ def PauseSubscription(self): return self.operator.call("PauseSubscription") def ResumeSubscription(self): - """Resume notification delivery for a paused subscription. + """ + Resume notification delivery for a paused subscription. Successfully processing this request returns the subscription to its active state and resumes the production of notifications. diff --git a/onvif/services/events/pullpoint.py b/onvif/services/events/pullpoint.py index d424395..acdc643 100644 --- a/onvif/services/events/pullpoint.py +++ b/onvif/services/events/pullpoint.py @@ -30,7 +30,8 @@ def __init__(self, xaddr=None, **kwargs): ) def PullMessages(self, Timeout, MessageLimit): - """This method pulls one or more messages from a PullPoint. + """ + This method pulls one or more messages from a PullPoint. The device shall provide the following PullMessages command for all SubscriptionManager endpoints returned by the CreatePullPointSubscription @@ -46,7 +47,8 @@ def PullMessages(self, Timeout, MessageLimit): ) def Seek(self, UtcTime, Reverse=None): - """This method readjusts the pull pointer into the past. + """ + This method readjusts the pull pointer into the past. A device supporting persistent notification storage shall provide the following Seek command for all SubscriptionManager endpoints returned by the @@ -59,7 +61,8 @@ def Seek(self, UtcTime, Reverse=None): return self.operator.call("Seek", UtcTime=UtcTime, Reverse=Reverse) def SetSynchronizationPoint(self): - """Properties inform a client about property creation, changes and deletion in a + """ + Properties inform a client about property creation, changes and deletion in a uniform way. When a client wants to synchronize its properties with the properties of the @@ -74,7 +77,8 @@ def SetSynchronizationPoint(self): return self.operator.call("SetSynchronizationPoint") def Unsubscribe(self): - """The device shall provide the following Unsubscribe command for all + """ + The device shall provide the following Unsubscribe command for all SubscriptionManager endpoints returned by the CreatePullPointSubscription command. diff --git a/onvif/services/events/subscription.py b/onvif/services/events/subscription.py index 2104a5e..6685767 100644 --- a/onvif/services/events/subscription.py +++ b/onvif/services/events/subscription.py @@ -35,8 +35,9 @@ def __init__(self, xaddr=None, **kwargs): ) def Renew(self, TerminationTime=None): - """An ONVIF compliant device shall support this command if it signals support - for [WS-Base Notification] via the MaxNotificationProducers capability. + """ + An ONVIF compliant device shall support this command if it signals support for + [WS-Base Notification] via the MaxNotificationProducers capability. The command shall at least support a Timeout of one minute. A device shall respond with both parameters CurrentTime and TerminationTime as utc using the @@ -45,7 +46,8 @@ def Renew(self, TerminationTime=None): return self.operator.call("Renew", TerminationTime=TerminationTime) def Unsubscribe(self): - """The device shall provide the following Unsubscribe command for all + """ + The device shall provide the following Unsubscribe command for all SubscriptionManager endpoints returned by the CreatePullPointSubscription command. diff --git a/onvif/services/imaging.py b/onvif/services/imaging.py index cf686ff..f31a58b 100644 --- a/onvif/services/imaging.py +++ b/onvif/services/imaging.py @@ -32,15 +32,17 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the imaging service. + """ + Returns the capabilities of the imaging service. The result is returned in a typed answer. """ return self.operator.call("GetServiceCapabilities") def GetOptions(self, VideoSourceToken): - """This operation gets the valid ranges for the imaging parameters that have - device specific ranges. + """ + This operation gets the valid ranges for the imaging parameters that have device + specific ranges. This command is mandatory for all device implementing the imaging service. The command returns all supported parameters and their ranges such that these can be @@ -73,7 +75,8 @@ def GetMoveOptions(self, VideoSourceToken): return self.operator.call("GetMoveOptions", VideoSourceToken=VideoSourceToken) def Move(self, VideoSourceToken, Focus): - """The Move command moves the focus lens in an absolute, a relative or in a + """ + The Move command moves the focus lens in an absolute, a relative or in a continuous manner from its current position. The speed argument is optional for absolute and relative control, but required @@ -101,7 +104,8 @@ def Move(self, VideoSourceToken, Focus): ) def GetStatus(self, VideoSourceToken): - """Via this command the current status of the Move operation can be requested. + """ + Via this command the current status of the Move operation can be requested. Supported for this command is available if the support for the Move operation is signalled via GetMoveOptions. @@ -109,7 +113,8 @@ def GetStatus(self, VideoSourceToken): return self.operator.call("GetStatus", VideoSourceToken=VideoSourceToken) def Stop(self, VideoSourceToken): - """The Stop command stops all ongoing focus movements of the lense. + """ + The Stop command stops all ongoing focus movements of the lense. A device with support for remote focus control as signalled via the GetMoveOptions supports this command. @@ -123,7 +128,8 @@ def GetPresets(self, VideoSourceToken): return self.operator.call("GetPresets", VideoSourceToken=VideoSourceToken) def GetCurrentPreset(self, VideoSourceToken): - """Via this command the last Imaging Preset applied can be requested. + """ + Via this command the last Imaging Preset applied can be requested. If the camera configuration does not match any of the existing Imaging Presets, the output of GetCurrentPreset shall be Empty. GetCurrentPreset shall return 0 @@ -132,8 +138,9 @@ def GetCurrentPreset(self, VideoSourceToken): return self.operator.call("GetCurrentPreset", VideoSourceToken=VideoSourceToken) def SetCurrentPreset(self, VideoSourceToken, PresetToken): - """The SetCurrentPreset command shall request a given Imaging Preset to be - applied to the specified Video Source. + """ + The SetCurrentPreset command shall request a given Imaging Preset to be applied + to the specified Video Source. SetCurrentPreset shall only be available for Video Sources with Imaging Presets Capability. Imaging Presets are defined by the Manufacturer, and offered as a diff --git a/onvif/services/media.py b/onvif/services/media.py index 29f8ed5..f5db7a5 100644 --- a/onvif/services/media.py +++ b/onvif/services/media.py @@ -33,7 +33,8 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the media service. + """ + Returns the capabilities of the media service. The result is returned in a typed answer. """ @@ -52,7 +53,8 @@ def GetAudioOutputs(self): return self.operator.call("GetAudioOutputs") def CreateProfile(self, Name, Token=None): - """This operation creates a new empty media profile. + """ + This operation creates a new empty media profile. The media profile shall be created in the device and shall be persistent (remain after reboot). A created profile shall be deletable and a device shall set the @@ -62,11 +64,13 @@ def CreateProfile(self, Name, Token=None): def GetProfile(self, ProfileToken): """If the profile token is already known, a profile can be fetched through the - GetProfile command.""" + GetProfile command. + """ return self.operator.call("GetProfile", ProfileToken=ProfileToken) def GetProfiles(self): - """Any endpoint can ask for the existing media profiles of a device using the + """ + Any endpoint can ask for the existing media profiles of a device using the GetProfiles command. Pre-configured or dynamically configured profiles can be retrieved using this @@ -76,7 +80,8 @@ def GetProfiles(self): return self.operator.call("GetProfiles") def AddVideoEncoderConfiguration(self, ProfileToken, ConfigurationToken): - """This operation adds a VideoEncoderConfiguration to an existing media profile. + """ + This operation adds a VideoEncoderConfiguration to an existing media profile. If a configuration exists in the media profile, it will be replaced. The change shall be persistent. A device shall support adding a compatible @@ -90,7 +95,8 @@ def AddVideoEncoderConfiguration(self, ProfileToken, ConfigurationToken): ) def AddVideoSourceConfiguration(self, ProfileToken, ConfigurationToken): - """This operation adds a VideoSourceConfiguration to an existing media profile. + """ + This operation adds a VideoSourceConfiguration to an existing media profile. If such a configuration exists in the media profile, it will be replaced. The change shall be persistent. @@ -102,8 +108,8 @@ def AddVideoSourceConfiguration(self, ProfileToken, ConfigurationToken): ) def AddAudioEncoderConfiguration(self, ProfileToken, ConfigurationToken): - """This operation adds an AudioEncoderConfiguration to an existing media - profile. + """ + This operation adds an AudioEncoderConfiguration to an existing media profile. If a configuration exists in the media profile, it will be replaced. The change shall be persistent. A device shall support adding a compatible @@ -117,7 +123,8 @@ def AddAudioEncoderConfiguration(self, ProfileToken, ConfigurationToken): ) def AddAudioSourceConfiguration(self, ProfileToken, ConfigurationToken): - """This operation adds an AudioSourceConfiguration to an existing media profile. + """ + This operation adds an AudioSourceConfiguration to an existing media profile. If a configuration exists in the media profile, it will be replaced. The change shall be persistent. @@ -129,7 +136,8 @@ def AddAudioSourceConfiguration(self, ProfileToken, ConfigurationToken): ) def AddPTZConfiguration(self, ProfileToken, ConfigurationToken): - """This operation adds a PTZConfiguration to an existing media profile. + """ + This operation adds a PTZConfiguration to an existing media profile. If a configuration exists in the media profile, it will be replaced. The change shall be persistent. Adding a PTZConfiguration to a media profile means that @@ -143,8 +151,8 @@ def AddPTZConfiguration(self, ProfileToken, ConfigurationToken): ) def AddVideoAnalyticsConfiguration(self, ProfileToken, ConfigurationToken): - """This operation adds a VideoAnalytics configuration to an existing media - profile. + """ + This operation adds a VideoAnalytics configuration to an existing media profile. If a configuration exists in the media profile, it will be replaced. The change shall be persistent. Adding a VideoAnalyticsConfiguration to a media profile @@ -163,7 +171,8 @@ def AddVideoAnalyticsConfiguration(self, ProfileToken, ConfigurationToken): ) def AddMetadataConfiguration(self, ProfileToken, ConfigurationToken): - """This operation adds a Metadata configuration to an existing media profile. + """ + This operation adds a Metadata configuration to an existing media profile. If a configuration exists in the media profile, it will be replaced. The change shall be persistent. Adding a MetadataConfiguration to a Profile means that @@ -177,7 +186,8 @@ def AddMetadataConfiguration(self, ProfileToken, ConfigurationToken): ) def AddAudioOutputConfiguration(self, ProfileToken, ConfigurationToken): - """This operation adds an AudioOutputConfiguration to an existing media profile. + """ + This operation adds an AudioOutputConfiguration to an existing media profile. If a configuration exists in the media profile, it will be replaced. The change shall be persistent. @@ -189,8 +199,8 @@ def AddAudioOutputConfiguration(self, ProfileToken, ConfigurationToken): ) def AddAudioDecoderConfiguration(self, ProfileToken, ConfigurationToken): - """This operation adds an AudioDecoderConfiguration to an existing media - profile. + """ + This operation adds an AudioDecoderConfiguration to an existing media profile. If a configuration exists in the media profile, it shall be replaced. The change shall be persistent. @@ -202,7 +212,8 @@ def AddAudioDecoderConfiguration(self, ProfileToken, ConfigurationToken): ) def RemoveVideoEncoderConfiguration(self, ProfileToken): - """This operation removes a VideoEncoderConfiguration from an existing media + """ + This operation removes a VideoEncoderConfiguration from an existing media profile. If the media profile does not contain a VideoEncoderConfiguration, the operation @@ -213,7 +224,8 @@ def RemoveVideoEncoderConfiguration(self, ProfileToken): ) def RemoveVideoSourceConfiguration(self, ProfileToken): - """This operation removes a VideoSourceConfiguration from an existing media + """ + This operation removes a VideoSourceConfiguration from an existing media profile. If the media profile does not contain a VideoSourceConfiguration, the operation @@ -226,7 +238,8 @@ def RemoveVideoSourceConfiguration(self, ProfileToken): ) def RemoveAudioEncoderConfiguration(self, ProfileToken): - """This operation removes an AudioEncoderConfiguration from an existing media + """ + This operation removes an AudioEncoderConfiguration from an existing media profile. If the media profile does not contain an AudioEncoderConfiguration, the @@ -237,7 +250,8 @@ def RemoveAudioEncoderConfiguration(self, ProfileToken): ) def RemoveAudioSourceConfiguration(self, ProfileToken): - """This operation removes an AudioSourceConfiguration from an existing media + """ + This operation removes an AudioSourceConfiguration from an existing media profile. If the media profile does not contain an AudioSourceConfiguration, the operation @@ -250,7 +264,8 @@ def RemoveAudioSourceConfiguration(self, ProfileToken): ) def RemovePTZConfiguration(self, ProfileToken): - """This operation removes a PTZConfiguration from an existing media profile. + """ + This operation removes a PTZConfiguration from an existing media profile. If the media profile does not contain a PTZConfiguration, the operation has no effect. The removal shall be persistent. @@ -258,7 +273,8 @@ def RemovePTZConfiguration(self, ProfileToken): return self.operator.call("RemovePTZConfiguration", ProfileToken=ProfileToken) def RemoveVideoAnalyticsConfiguration(self, ProfileToken): - """This operation removes a VideoAnalyticsConfiguration from an existing media + """ + This operation removes a VideoAnalyticsConfiguration from an existing media profile. If the media profile does not contain a VideoAnalyticsConfiguration, the @@ -269,8 +285,8 @@ def RemoveVideoAnalyticsConfiguration(self, ProfileToken): ) def RemoveMetadataConfiguration(self, ProfileToken): - """This operation removes a MetadataConfiguration from an existing media - profile. + """ + This operation removes a MetadataConfiguration from an existing media profile. If the media profile does not contain a MetadataConfiguration, the operation has no effect. The removal shall be persistent. @@ -280,7 +296,8 @@ def RemoveMetadataConfiguration(self, ProfileToken): ) def RemoveAudioOutputConfiguration(self, ProfileToken): - """This operation removes an AudioOutputConfiguration from an existing media + """ + This operation removes an AudioOutputConfiguration from an existing media profile. If the media profile does not contain an AudioOutputConfiguration, the operation @@ -291,7 +308,8 @@ def RemoveAudioOutputConfiguration(self, ProfileToken): ) def RemoveAudioDecoderConfiguration(self, ProfileToken): - """This operation removes an AudioDecoderConfiguration from an existing media + """ + This operation removes an AudioDecoderConfiguration from an existing media profile. If the media profile does not contain an AudioDecoderConfiguration, the @@ -302,7 +320,8 @@ def RemoveAudioDecoderConfiguration(self, ProfileToken): ) def DeleteProfile(self, ProfileToken): - """This operation deletes a profile. + """ + This operation deletes a profile. This change shall always be persistent. Deletion of a profile is only possible for non-fixed profiles @@ -310,7 +329,8 @@ def DeleteProfile(self, ProfileToken): return self.operator.call("DeleteProfile", ProfileToken=ProfileToken) def GetVideoSourceConfigurations(self): - """This operation lists all existing video source configurations for a device. + """ + This operation lists all existing video source configurations for a device. The client need not know anything about the video source configurations in order to use the command. @@ -318,7 +338,8 @@ def GetVideoSourceConfigurations(self): return self.operator.call("GetVideoSourceConfigurations") def GetVideoEncoderConfigurations(self): - """This operation lists all existing video encoder configurations of a device. + """ + This operation lists all existing video encoder configurations of a device. This command lists all configured video encoder configurations in a device. The client need not know anything apriori about the video encoder configurations in @@ -327,7 +348,8 @@ def GetVideoEncoderConfigurations(self): return self.operator.call("GetVideoEncoderConfigurations") def GetAudioSourceConfigurations(self): - """This operation lists all existing audio source configurations of a device. + """ + This operation lists all existing audio source configurations of a device. This command lists all audio source configurations in a device. The client need not know anything apriori about the audio source configurations in order to use @@ -336,7 +358,8 @@ def GetAudioSourceConfigurations(self): return self.operator.call("GetAudioSourceConfigurations") def GetAudioEncoderConfigurations(self): - """This operation lists all existing device audio encoder configurations. + """ + This operation lists all existing device audio encoder configurations. The client need not know anything apriori about the audio encoder configurations in order to use the command. @@ -344,7 +367,8 @@ def GetAudioEncoderConfigurations(self): return self.operator.call("GetAudioEncoderConfigurations") def GetVideoAnalyticsConfigurations(self): - """This operation lists all video analytics configurations of a device. + """ + This operation lists all video analytics configurations of a device. This command lists all configured video analytics in a device. The client need not know anything apriori about the video analytics in order to use the command. @@ -352,7 +376,8 @@ def GetVideoAnalyticsConfigurations(self): return self.operator.call("GetVideoAnalyticsConfigurations") def GetMetadataConfigurations(self): - """This operation lists all existing metadata configurations. + """ + This operation lists all existing metadata configurations. The client need not know anything apriori about the metadata in order to use the command. @@ -360,7 +385,8 @@ def GetMetadataConfigurations(self): return self.operator.call("GetMetadataConfigurations") def GetAudioOutputConfigurations(self): - """This command lists all existing AudioOutputConfigurations of a device. + """ + This command lists all existing AudioOutputConfigurations of a device. The NVC need not know anything apriori about the audio configurations to use this command. @@ -368,7 +394,8 @@ def GetAudioOutputConfigurations(self): return self.operator.call("GetAudioOutputConfigurations") def GetAudioDecoderConfigurations(self): - """This command lists all existing AudioDecoderConfigurations of a device. + """ + This command lists all existing AudioDecoderConfigurations of a device. The NVC need not know anything apriori about the audio decoder configurations in order to use this command. @@ -377,7 +404,8 @@ def GetAudioDecoderConfigurations(self): def GetVideoSourceConfiguration(self, ConfigurationToken): """If the video source configuration token is already known, the video source - configuration can be fetched through the GetVideoSourceConfiguration command.""" + configuration can be fetched through the GetVideoSourceConfiguration command. + """ return self.operator.call( "GetVideoSourceConfiguration", ConfigurationToken=ConfigurationToken ) @@ -385,42 +413,48 @@ def GetVideoSourceConfiguration(self, ConfigurationToken): def GetVideoEncoderConfiguration(self, ConfigurationToken): """If the video encoder configuration token is already known, the encoder configuration can be fetched through the GetVideoEncoderConfiguration - command.""" + command. + """ return self.operator.call( "GetVideoEncoderConfiguration", ConfigurationToken=ConfigurationToken ) def GetAudioSourceConfiguration(self, ConfigurationToken): """The GetAudioSourceConfiguration command fetches the audio source - configurations if the audio source configuration token is already known.""" + configurations if the audio source configuration token is already known. + """ return self.operator.call( "GetAudioSourceConfiguration", ConfigurationToken=ConfigurationToken ) def GetAudioEncoderConfiguration(self, ConfigurationToken): """The GetAudioEncoderConfiguration command fetches the encoder configuration if - the audio encoder configuration token is known.""" + the audio encoder configuration token is known. + """ return self.operator.call( "GetAudioEncoderConfiguration", ConfigurationToken=ConfigurationToken ) def GetVideoAnalyticsConfiguration(self, ConfigurationToken): """The GetVideoAnalyticsConfiguration command fetches the video analytics - configuration if the video analytics token is known.""" + configuration if the video analytics token is known. + """ return self.operator.call( "GetVideoAnalyticsConfiguration", ConfigurationToken=ConfigurationToken ) def GetMetadataConfiguration(self, ConfigurationToken): """The GetMetadataConfiguration command fetches the metadata configuration if - the metadata token is known.""" + the metadata token is known. + """ return self.operator.call( "GetMetadataConfiguration", ConfigurationToken=ConfigurationToken ) def GetAudioOutputConfiguration(self, ConfigurationToken): """If the audio output configuration token is already known, the output - configuration can be fetched through the GetAudioOutputConfiguration command.""" + configuration can be fetched through the GetAudioOutputConfiguration command. + """ return self.operator.call( "GetAudioOutputConfiguration", ConfigurationToken=ConfigurationToken ) @@ -428,14 +462,16 @@ def GetAudioOutputConfiguration(self, ConfigurationToken): def GetAudioDecoderConfiguration(self, ConfigurationToken): """If the audio decoder configuration token is already known, the decoder configuration can be fetched through the GetAudioDecoderConfiguration - command.""" + command. + """ return self.operator.call( "GetAudioDecoderConfiguration", ConfigurationToken=ConfigurationToken ) def GetCompatibleVideoEncoderConfigurations(self, ProfileToken): - """This operation lists all the video encoder configurations of the device that - are compatible with a certain media profile. + """ + This operation lists all the video encoder configurations of the device that are + compatible with a certain media profile. Each of the returned configurations shall be a valid input parameter for the AddVideoEncoderConfiguration command on the media profile. The result will vary @@ -446,8 +482,9 @@ def GetCompatibleVideoEncoderConfigurations(self, ProfileToken): ) def GetCompatibleVideoSourceConfigurations(self, ProfileToken): - """This operation requests all the video source configurations of the device - that are compatible with a certain media profile. + """ + This operation requests all the video source configurations of the device that + are compatible with a certain media profile. Each of the returned configurations shall be a valid input parameter for the AddVideoSourceConfiguration command on the media profile. The result will vary @@ -458,7 +495,8 @@ def GetCompatibleVideoSourceConfigurations(self, ProfileToken): ) def GetCompatibleAudioEncoderConfigurations(self, ProfileToken): - """This operation requests all audio encoder configurations of a device that are + """ + This operation requests all audio encoder configurations of a device that are compatible with a certain media profile. Each of the returned configurations shall be a valid input parameter for the @@ -470,8 +508,9 @@ def GetCompatibleAudioEncoderConfigurations(self, ProfileToken): ) def GetCompatibleAudioSourceConfigurations(self, ProfileToken): - """This operation requests all audio source configurations of the device that - are compatible with a certain media profile. + """ + This operation requests all audio source configurations of the device that are + compatible with a certain media profile. Each of the returned configurations shall be a valid input parameter for the AddAudioEncoderConfiguration command on the media profile. The result varies @@ -482,8 +521,9 @@ def GetCompatibleAudioSourceConfigurations(self, ProfileToken): ) def GetCompatibleVideoAnalyticsConfigurations(self, ProfileToken): - """This operation requests all video analytic configurations of the device that - are compatible with a certain media profile. + """ + This operation requests all video analytic configurations of the device that are + compatible with a certain media profile. Each of the returned configurations shall be a valid input parameter for the AddVideoAnalyticsConfiguration command on the media profile. The result varies @@ -494,8 +534,9 @@ def GetCompatibleVideoAnalyticsConfigurations(self, ProfileToken): ) def GetCompatibleMetadataConfigurations(self, ProfileToken): - """This operation requests all the metadata configurations of the device that - are compatible with a certain media profile. + """ + This operation requests all the metadata configurations of the device that are + compatible with a certain media profile. Each of the returned configurations shall be a valid input parameter for the AddMetadataConfiguration command on the media profile. The result varies @@ -506,7 +547,8 @@ def GetCompatibleMetadataConfigurations(self, ProfileToken): ) def GetCompatibleAudioOutputConfigurations(self, ProfileToken): - """This command lists all audio output configurations of a device that are + """ + This command lists all audio output configurations of a device that are compatible with a certain media profile. Each returned configuration shall be a valid input for the @@ -517,8 +559,9 @@ def GetCompatibleAudioOutputConfigurations(self, ProfileToken): ) def GetCompatibleAudioDecoderConfigurations(self, ProfileToken): - """This operation lists all the audio decoder configurations of the device that - are compatible with a certain media profile. + """ + This operation lists all the audio decoder configurations of the device that are + compatible with a certain media profile. Each of the returned configurations shall be a valid input parameter for the AddAudioDecoderConfiguration command on the media profile. @@ -528,7 +571,8 @@ def GetCompatibleAudioDecoderConfigurations(self, ProfileToken): ) def SetVideoSourceConfiguration(self, Configuration, ForcePersistence): - """This operation modifies a video source configuration. + """ + This operation modifies a video source configuration. The ForcePersistence flag indicates if the changes shall remain after reboot of the device. Running streams using this configuration may be immediately updated @@ -544,7 +588,8 @@ def SetVideoSourceConfiguration(self, Configuration, ForcePersistence): ) def SetVideoEncoderConfiguration(self, Configuration, ForcePersistence): - """This operation modifies a video encoder configuration. + """ + This operation modifies a video encoder configuration. The ForcePersistence flag indicates if the changes shall remain after reboot of the device. Changes in the Multicast settings shall always be persistent. @@ -565,7 +610,8 @@ def SetVideoEncoderConfiguration(self, Configuration, ForcePersistence): ) def SetAudioSourceConfiguration(self, Configuration, ForcePersistence): - """This operation modifies an audio source configuration. + """ + This operation modifies an audio source configuration. The ForcePersistence flag indicates if the changes shall remain after reboot of the device. Running streams using this configuration may be immediately updated @@ -580,7 +626,8 @@ def SetAudioSourceConfiguration(self, Configuration, ForcePersistence): ) def SetAudioEncoderConfiguration(self, Configuration, ForcePersistence): - """This operation modifies an audio encoder configuration. + """ + This operation modifies an audio encoder configuration. The ForcePersistence flag indicates if the changes shall remain after reboot of the device. Running streams using this configuration may be immediately updated @@ -596,7 +643,8 @@ def SetAudioEncoderConfiguration(self, Configuration, ForcePersistence): ) def SetVideoAnalyticsConfiguration(self, Configuration, ForcePersistence): - """A video analytics configuration is modified using this command. + """ + A video analytics configuration is modified using this command. The ForcePersistence flag indicates if the changes shall remain after reboot of the device or not. Running streams using this configuration shall be immediately @@ -612,7 +660,8 @@ def SetVideoAnalyticsConfiguration(self, Configuration, ForcePersistence): ) def SetMetadataConfiguration(self, Configuration, ForcePersistence): - """This operation modifies a metadata configuration. + """ + This operation modifies a metadata configuration. The ForcePersistence flag indicates if the changes shall remain after reboot of the device. Changes in the Multicast settings shall always be persistent. @@ -628,7 +677,8 @@ def SetMetadataConfiguration(self, Configuration, ForcePersistence): ) def SetAudioOutputConfiguration(self, Configuration, ForcePersistence): - """This operation modifies an audio output configuration. + """ + This operation modifies an audio output configuration. The ForcePersistence flag indicates if the changes shall remain after reboot of the device. @@ -640,7 +690,8 @@ def SetAudioOutputConfiguration(self, Configuration, ForcePersistence): ) def SetAudioDecoderConfiguration(self, Configuration, ForcePersistence): - """This operation modifies an audio decoder configuration. + """ + This operation modifies an audio decoder configuration. The ForcePersistence flag indicates if the changes shall remain after reboot of the device. @@ -654,7 +705,8 @@ def SetAudioDecoderConfiguration(self, Configuration, ForcePersistence): def GetVideoSourceConfigurationOptions( self, ConfigurationToken=None, ProfileToken=None ): - """This operation returns the available options (supported values and ranges for + """ + This operation returns the available options (supported values and ranges for video source configuration parameters) when the video source parameters are reconfigured If a video source configuration is specified, the options shall concern that particular configuration. @@ -671,7 +723,8 @@ def GetVideoSourceConfigurationOptions( def GetVideoEncoderConfigurationOptions( self, ConfigurationToken=None, ProfileToken=None ): - """This operation returns the available options (supported values and ranges for + """ + This operation returns the available options (supported values and ranges for video encoder configuration parameters) when the video encoder parameters are reconfigured. @@ -695,7 +748,8 @@ def GetVideoEncoderConfigurationOptions( def GetAudioSourceConfigurationOptions( self, ConfigurationToken=None, ProfileToken=None ): - """This operation returns the available options (supported values and ranges for + """ + This operation returns the available options (supported values and ranges for audio source configuration parameters) when the audio source parameters are reconfigured. @@ -714,7 +768,8 @@ def GetAudioEncoderConfigurationOptions( ): """This operation returns the available options (supported values and ranges for audio encoder configuration parameters) when the audio encoder parameters are - reconfigured.""" + reconfigured. + """ return self.operator.call( "GetAudioEncoderConfigurationOptions", ConfigurationToken=ConfigurationToken, @@ -725,7 +780,8 @@ def GetMetadataConfigurationOptions( self, ConfigurationToken=None, ProfileToken=None ): """This operation returns the available options (supported values and ranges for - metadata configuration parameters) for changing the metadata configuration.""" + metadata configuration parameters) for changing the metadata configuration. + """ return self.operator.call( "GetMetadataConfigurationOptions", ConfigurationToken=ConfigurationToken, @@ -736,7 +792,8 @@ def GetAudioOutputConfigurationOptions( self, ConfigurationToken=None, ProfileToken=None ): """This operation returns the available options (supported values and ranges for - audio output configuration parameters) for configuring an audio output.""" + audio output configuration parameters) for configuring an audio output. + """ return self.operator.call( "GetAudioOutputConfigurationOptions", ConfigurationToken=ConfigurationToken, @@ -747,7 +804,8 @@ def GetAudioDecoderConfigurationOptions( self, ConfigurationToken=None, ProfileToken=None ): """This command list the audio decoding capabilities for a given profile and - configuration of a device.""" + configuration of a device. + """ return self.operator.call( "GetAudioDecoderConfigurationOptions", ConfigurationToken=ConfigurationToken, @@ -757,7 +815,8 @@ def GetAudioDecoderConfigurationOptions( def GetGuaranteedNumberOfVideoEncoderInstances(self, ConfigurationToken): """The GetGuaranteedNumberOfVideoEncoderInstances command can be used to request the minimum number of guaranteed video encoder instances (applications) per - Video Source Configuration.""" + Video Source Configuration. + """ return self.operator.call( "GetGuaranteedNumberOfVideoEncoderInstances", ConfigurationToken=ConfigurationToken, @@ -790,7 +849,8 @@ def GetStreamUri(self, StreamSetup, ProfileToken): ) def StartMulticastStreaming(self, ProfileToken): - """This command starts multicast streaming using a specified media profile of a + """ + This command starts multicast streaming using a specified media profile of a device. Streaming continues until StopMulticastStreaming is called for the same Profile. @@ -803,12 +863,14 @@ def StartMulticastStreaming(self, ProfileToken): def StopMulticastStreaming(self, ProfileToken): """This command stop multicast streaming using a specified media profile of a - device.""" + device. + """ return self.operator.call("StopMulticastStreaming", ProfileToken=ProfileToken) def SetSynchronizationPoint(self, ProfileToken): - """Synchronization points allow clients to decode and correctly use all data - after the synchronization point. + """ + Synchronization points allow clients to decode and correctly use all data after + the synchronization point. For example, if a video stream is configured with a large I-frame distance and a client loses a single packet, the client does not display video until the next @@ -825,7 +887,8 @@ def SetSynchronizationPoint(self, ProfileToken): return self.operator.call("SetSynchronizationPoint", ProfileToken=ProfileToken) def GetSnapshotUri(self, ProfileToken): - """A client uses the GetSnapshotUri command to obtain a JPEG snapshot from the + """ + A client uses the GetSnapshotUri command to obtain a JPEG snapshot from the device. The returned URI shall remain valid indefinitely even if the profile is changed. @@ -840,7 +903,8 @@ def GetSnapshotUri(self, ProfileToken): return self.operator.call("GetSnapshotUri", ProfileToken=ProfileToken) def GetVideoSourceModes(self, VideoSourceToken): - """A device returns the information for current video source mode and settable + """ + A device returns the information for current video source mode and settable video source modes of specified video source. A device that indicates a capability of VideoSourceModes shall support this @@ -851,8 +915,9 @@ def GetVideoSourceModes(self, VideoSourceToken): ) def SetVideoSourceMode(self, VideoSourceToken, VideoSourceModeToken): - """SetVideoSourceMode changes the media profile structure relating to video - source for the specified video source mode. + """ + SetVideoSourceMode changes the media profile structure relating to video source + for the specified video source mode. A device that indicates a capability of VideoSourceModes shall support this command. The behavior after changing the mode is not defined in this diff --git a/onvif/services/media2.py b/onvif/services/media2.py index fa71de1..b97e3d0 100644 --- a/onvif/services/media2.py +++ b/onvif/services/media2.py @@ -32,14 +32,16 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the media service. + """ + Returns the capabilities of the media service. The result is returned in a typed answer. """ return self.operator.call("GetServiceCapabilities") def CreateProfile(self, Name, Configuration=None): - """This operation creates a new media profile. + """ + This operation creates a new media profile. A created profile created via this method may be deleted via the DeleteProfile method. Optionally Configurations can be assigned to the profile on creation. @@ -51,7 +53,8 @@ def CreateProfile(self, Name, Configuration=None): ) def GetProfiles(self, Token=None, Type=None): - """Retrieve the profile with the specified token or all defined media profiles. + """ + Retrieve the profile with the specified token or all defined media profiles. - If no Type is provided the returned profiles shall contain no configuration information. @@ -65,7 +68,8 @@ def GetProfiles(self, Token=None, Type=None): return self.operator.call("GetProfiles", Token=Token, Type=Type) def AddConfiguration(self, ProfileToken, Name=None, Configuration=None): - """This operation adds one or more Configurations to an existing media profile. + """ + This operation adds one or more Configurations to an existing media profile. If a configuration exists in the media profile, it will be replaced. A device shall support adding a compatible Configuration to a Profile containing a @@ -82,8 +86,8 @@ def AddConfiguration(self, ProfileToken, Name=None, Configuration=None): ) def RemoveConfiguration(self, ProfileToken, Configuration): - """This operation removes the listed configurations from an existing media - profile. + """ + This operation removes the listed configurations from an existing media profile. If the media profile does not contain one of the listed configurations that item shall be ignored. @@ -95,15 +99,17 @@ def RemoveConfiguration(self, ProfileToken, Configuration): ) def DeleteProfile(self, Token): - """This operation deletes a profile. + """ + This operation deletes a profile. Deletion of a profile is only possible for non-fixed profiles """ return self.operator.call("DeleteProfile", Token=Token) def GetVideoSourceConfigurations(self, ConfigurationToken=None, ProfileToken=None): - """By default this operation lists all existing video source configurations for - a device. + """ + By default this operation lists all existing video source configurations for a + device. Provide a profile token to list only configurations that are compatible with the profile. If a configuration token is provided only a single configuration will @@ -116,8 +122,9 @@ def GetVideoSourceConfigurations(self, ConfigurationToken=None, ProfileToken=Non ) def GetVideoEncoderConfigurations(self, ConfigurationToken=None, ProfileToken=None): - """By default this operation lists all existing video encoder configurations for - a device. + """ + By default this operation lists all existing video encoder configurations for a + device. Provide a profile token to list only configurations that are compatible with the profile. If a configuration token is provided only a single configuration will @@ -130,8 +137,9 @@ def GetVideoEncoderConfigurations(self, ConfigurationToken=None, ProfileToken=No ) def GetAudioSourceConfigurations(self, ConfigurationToken=None, ProfileToken=None): - """By default this operation lists all existing audio source configurations for - a device. + """ + By default this operation lists all existing audio source configurations for a + device. Provide a profile token to list only configurations that are compatible with the profile. If a configuration token is provided only a single configuration will @@ -144,8 +152,9 @@ def GetAudioSourceConfigurations(self, ConfigurationToken=None, ProfileToken=Non ) def GetAudioEncoderConfigurations(self, ConfigurationToken=None, ProfileToken=None): - """By default this operation lists all existing audio encoder configurations for - a device. + """ + By default this operation lists all existing audio encoder configurations for a + device. Provide a profile token to list only configurations that are compatible with the profile. If a configuration token is provided only a single configuration will @@ -158,8 +167,9 @@ def GetAudioEncoderConfigurations(self, ConfigurationToken=None, ProfileToken=No ) def GetAnalyticsConfigurations(self, ConfigurationToken=None, ProfileToken=None): - """By default this operation lists all existing video analytics configurations - for a device. + """ + By default this operation lists all existing video analytics configurations for + a device. Provide a profile token to list only configurations that are compatible with the profile. If a configuration token is provided only a single configuration will @@ -172,7 +182,8 @@ def GetAnalyticsConfigurations(self, ConfigurationToken=None, ProfileToken=None) ) def GetMetadataConfigurations(self, ConfigurationToken=None, ProfileToken=None): - """By default this operation lists all existing metadata configurations for a + """ + By default this operation lists all existing metadata configurations for a device. Provide a profile token to list only configurations that are compatible with the @@ -186,8 +197,9 @@ def GetMetadataConfigurations(self, ConfigurationToken=None, ProfileToken=None): ) def GetAudioOutputConfigurations(self, ConfigurationToken=None, ProfileToken=None): - """By default this operation lists all existing audio output configurations for - a device. + """ + By default this operation lists all existing audio output configurations for a + device. Provide a profile token to list only configurations that are compatible with the profile. If a configuration token is provided only a single configuration will @@ -200,8 +212,9 @@ def GetAudioOutputConfigurations(self, ConfigurationToken=None, ProfileToken=Non ) def GetAudioDecoderConfigurations(self, ConfigurationToken=None, ProfileToken=None): - """By default this operation lists all existing audio decoder configurations for - a device. + """ + By default this operation lists all existing audio decoder configurations for a + device. Provide a profile token to list only configurations that are compatible with the profile. If a configuration token is provided only a single configuration will @@ -214,7 +227,8 @@ def GetAudioDecoderConfigurations(self, ConfigurationToken=None, ProfileToken=No ) def SetVideoSourceConfiguration(self, Configuration): - """This operation modifies a video source configuration. + """ + This operation modifies a video source configuration. Running streams using this configuration may be immediately updated according to the new settings. The changes are not guaranteed to take effect unless the @@ -226,7 +240,8 @@ def SetVideoSourceConfiguration(self, Configuration): ) def SetVideoEncoderConfiguration(self, Configuration): - """This operation modifies a video encoder configuration. + """ + This operation modifies a video encoder configuration. Running streams using this configuration may be immediately updated according to the new settings. The changes are not guaranteed to take effect unless the @@ -243,7 +258,8 @@ def SetVideoEncoderConfiguration(self, Configuration): ) def SetAudioSourceConfiguration(self, Configuration): - """This operation modifies an audio source configuration. + """ + This operation modifies an audio source configuration. Running streams using this configuration may be immediately updated according to the new settings. The changes are not guaranteed to take effect unless the @@ -255,7 +271,8 @@ def SetAudioSourceConfiguration(self, Configuration): ) def SetAudioEncoderConfiguration(self, Configuration): - """This operation modifies an audio encoder configuration. + """ + This operation modifies an audio encoder configuration. Running streams using this configuration may be immediately updated according to the new settings. The changes are not guaranteed to take effect unless the @@ -267,7 +284,8 @@ def SetAudioEncoderConfiguration(self, Configuration): ) def SetMetadataConfiguration(self, Configuration): - """This operation modifies a metadata configuration. + """ + This operation modifies a metadata configuration. Running streams using this configuration may be updated immediately according to the new settings. The changes are not guaranteed to take effect unless the @@ -294,7 +312,8 @@ def SetAudioDecoderConfiguration(self, Configuration): "Use SetEQPresetConfiguration instead. See https://github.com/onvif/specs/pull/830" ) def SetEQPreset(self, Configuration): - """Set Audio EQPreset using the legacy ONVIF operation name. + """ + Set Audio EQPreset using the legacy ONVIF operation name. This operation is retained for compatibility with devices implementing the ONVIF 25.12 operation name before it was renamed in later specifications. @@ -320,7 +339,8 @@ def SetEQPresetConfiguration(self, Configuration): def GetVideoSourceConfigurationOptions( self, ConfigurationToken=None, ProfileToken=None ): - """This operation returns the available options (supported values and ranges for + """ + This operation returns the available options (supported values and ranges for video source configuration parameters) when the video source parameters are reconfigured If a video source configuration is specified, the options shall concern that particular configuration. @@ -337,7 +357,8 @@ def GetVideoSourceConfigurationOptions( def GetVideoEncoderConfigurationOptions( self, ConfigurationToken=None, ProfileToken=None ): - """This operation returns the available options (supported values and ranges for + """ + This operation returns the available options (supported values and ranges for video encoder configuration parameters) when the video encoder parameters are reconfigured. @@ -356,7 +377,8 @@ def GetVideoEncoderConfigurationOptions( def GetAudioSourceConfigurationOptions( self, ConfigurationToken=None, ProfileToken=None ): - """This operation returns the available options (supported values and ranges for + """ + This operation returns the available options (supported values and ranges for audio source configuration parameters) when the audio source parameters are reconfigured. @@ -375,7 +397,8 @@ def GetAudioEncoderConfigurationOptions( ): """This operation returns the available options (supported values and ranges for audio encoder configuration parameters) when the audio encoder parameters are - reconfigured.""" + reconfigured. + """ return self.operator.call( "GetAudioEncoderConfigurationOptions", ConfigurationToken=ConfigurationToken, @@ -386,7 +409,8 @@ def GetMetadataConfigurationOptions( self, ConfigurationToken=None, ProfileToken=None ): """This operation returns the available options (supported values and ranges for - metadata configuration parameters) for changing the metadata configuration.""" + metadata configuration parameters) for changing the metadata configuration. + """ return self.operator.call( "GetMetadataConfigurationOptions", ConfigurationToken=ConfigurationToken, @@ -396,7 +420,8 @@ def GetMetadataConfigurationOptions( def GetAudioOutputConfigurationOptions( self, ConfigurationToken=None, ProfileToken=None ): - """This operation returns the available options (supported values and ranges for + """ + This operation returns the available options (supported values and ranges for audio output configuration parameters) for configuring an audio output. To retrieve the EQPresetList, a valid ConfigurationToken must be provided. If @@ -413,7 +438,8 @@ def GetAudioDecoderConfigurationOptions( self, ConfigurationToken=None, ProfileToken=None ): """This command list the audio decoding capabilities for a given profile and - configuration of a device.""" + configuration of a device. + """ return self.operator.call( "GetAudioDecoderConfigurationOptions", ConfigurationToken=ConfigurationToken, @@ -423,14 +449,16 @@ def GetAudioDecoderConfigurationOptions( def GetVideoEncoderInstances(self, ConfigurationToken): """The GetVideoEncoderInstances command can be used to request the minimum number of guaranteed video encoder instances (applications) per Video Source - Configuration.""" + Configuration. + """ return self.operator.call( "GetVideoEncoderInstances", ConfigurationToken=ConfigurationToken ) def GetStreamUri(self, Protocol, ProfileToken): - """This operation requests a URI that can be used to initiate a live media - stream using RTSP as the control protocol. + """ + This operation requests a URI that can be used to initiate a live media stream + using RTSP as the control protocol. The returned URI shall remain valid indefinitely even if the profile is changed. @@ -456,7 +484,8 @@ def GetStreamUri(self, Protocol, ProfileToken): ) def StartMulticastStreaming(self, ProfileToken): - """This command starts multicast streaming using a specified media profile of a + """ + This command starts multicast streaming using a specified media profile of a device. Streaming continues until StopMulticastStreaming is called for the same Profile. @@ -469,12 +498,14 @@ def StartMulticastStreaming(self, ProfileToken): def StopMulticastStreaming(self, ProfileToken): """This command stops multicast streaming using a specified media profile of a - device.""" + device. + """ return self.operator.call("StopMulticastStreaming", ProfileToken=ProfileToken) def SetSynchronizationPoint(self, ProfileToken): - """Synchronization points allow clients to decode and correctly use all data - after the synchronization point. + """ + Synchronization points allow clients to decode and correctly use all data after + the synchronization point. For example, if a video stream is configured with a large I-frame distance and a client loses a single packet, the client does not display video until the next @@ -491,7 +522,8 @@ def SetSynchronizationPoint(self, ProfileToken): return self.operator.call("SetSynchronizationPoint", ProfileToken=ProfileToken) def GetSnapshotUri(self, ProfileToken): - """A client uses the GetSnapshotUri command to obtain a JPEG snapshot from the + """ + A client uses the GetSnapshotUri command to obtain a JPEG snapshot from the device. The returned URI shall remain valid indefinitely even if the profile is changed. @@ -504,7 +536,8 @@ def GetSnapshotUri(self, ProfileToken): return self.operator.call("GetSnapshotUri", ProfileToken=ProfileToken) def GetVideoSourceModes(self, VideoSourceToken): - """A device returns the information for current video source mode and settable + """ + A device returns the information for current video source mode and settable video source modes of specified video source. A device that indicates a capability of VideoSourceModes shall support this @@ -515,8 +548,9 @@ def GetVideoSourceModes(self, VideoSourceToken): ) def SetVideoSourceMode(self, VideoSourceToken, VideoSourceModeToken): - """SetVideoSourceMode changes the media profile structure relating to video - source for the specified video source mode. + """ + SetVideoSourceMode changes the media profile structure relating to video source + for the specified video source mode. A device that indicates a capability of VideoSourceModes shall support this command. The behavior after changing the mode is not defined in this @@ -529,7 +563,8 @@ def SetVideoSourceMode(self, VideoSourceToken, VideoSourceModeToken): ) def GetOSDs(self, OSDToken=None, ConfigurationToken=None): - """This operation lists existing OSD configurations for the device. + """ + This operation lists existing OSD configurations for the device. - If an OSD token is provided the device shall respond with the requested configuration or provide an error if it does not exist. @@ -563,7 +598,8 @@ def DeleteOSD(self, OSDToken): return self.operator.call("DeleteOSD", OSDToken=OSDToken) def GetMasks(self, Token=None, ConfigurationToken=None): - """This operation lists existing Mask configurations for the device. + """ + This operation lists existing Mask configurations for the device. - If an Mask token is provided the device shall respond with the requested configuration or provide an error if it does not exist. @@ -607,7 +643,8 @@ def SetWebRTCConfigurations(self, WebRTCConfiguration=None): ) def GetAudioClips(self, Token=None): - """This operation retrieves audio clip configurations from the device. + """ + This operation retrieves audio clip configurations from the device. If an audio clip token is provided, the device shall return the audio clip configuration associated with that token. If no token is provided, the device @@ -616,7 +653,8 @@ def GetAudioClips(self, Token=None): return self.operator.call("GetAudioClips", Token=Token) def AddAudioClip(self, Configuration, Token=None): - """This operation adds audio clip configuration to the device and provides audio + """ + This operation adds audio clip configuration to the device and provides audio clip upload URI to the client. The response to the command includes an HTTP URL to which the audio clip may be @@ -630,13 +668,15 @@ def AddAudioClip(self, Configuration, Token=None): def SetAudioClip(self, Token, Configuration): """This operation modifies the existing audio clip configuration on the - device.""" + device. + """ return self.operator.call( "SetAudioClip", Token=Token, Configuration=Configuration ) def DeleteAudioClip(self, Token): - """This operation deletes the audio clip configuration and the associated audio + """ + This operation deletes the audio clip configuration and the associated audio clip on the device. The audio clip should be de-associated from the event or schedule trigger if it @@ -673,7 +713,8 @@ def AddTTSAudioClip(self, Configuration, TTSConfiguration, Token=None): def GetPlayingAudioClips(self): """This operation retrieves audio clips information which are playing currently - in the device.""" + in the device. + """ return self.operator.call("GetPlayingAudioClips") def GetMulticastAudioDecoderConfigurationOptions(self, ConfigurationToken=None): diff --git a/onvif/services/ptz.py b/onvif/services/ptz.py index 91390ad..413ceba 100644 --- a/onvif/services/ptz.py +++ b/onvif/services/ptz.py @@ -32,14 +32,16 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the PTZ service. + """ + Returns the capabilities of the PTZ service. The result is returned in a typed answer. """ return self.operator.call("GetServiceCapabilities") def GetConfigurations(self): - """Get all the existing PTZConfigurations from the device. + """ + Get all the existing PTZConfigurations from the device. The default Position/Translation/Velocity Spaces are introduced to allow NVCs sending move requests without the need to specify a certain coordinate system. @@ -62,7 +64,8 @@ def GetConfigurations(self): return self.operator.call("GetConfigurations") def GetPresets(self, ProfileToken): - """Operation to request all PTZ presets for the PTZNode in the selected profile. + """ + Operation to request all PTZ presets for the PTZNode in the selected profile. The operation is supported if there is support for at least on PTZ preset by the PTZNode. @@ -70,9 +73,9 @@ def GetPresets(self, ProfileToken): return self.operator.call("GetPresets", ProfileToken=ProfileToken) def SetPreset(self, ProfileToken, PresetName=None, PresetToken=None): - """The SetPreset command saves the current device position parameters so that - the device can move to the saved preset position through the GotoPreset - operation. + """ + The SetPreset command saves the current device position parameters so that the + device can move to the saved preset position through the GotoPreset operation. In order to create a new preset, the SetPresetRequest contains no PresetToken. If creation is successful, the Response contains the PresetToken which uniquely @@ -91,7 +94,8 @@ def SetPreset(self, ProfileToken, PresetName=None, PresetToken=None): ) def RemovePreset(self, ProfileToken, PresetToken): - """Operation to remove a PTZ preset for the Node in the selected profile. + """ + Operation to remove a PTZ preset for the Node in the selected profile. The operation is supported if the PresetPosition capability exists for the Node in the selected profile. @@ -101,7 +105,8 @@ def RemovePreset(self, ProfileToken, PresetToken): ) def GotoPreset(self, ProfileToken, PresetToken, Speed=None): - """Operation to go to a saved preset position for the PTZNode in the selected + """ + Operation to go to a saved preset position for the PTZNode in the selected profile. The operation is supported if there is support for at least on PTZ preset by the @@ -119,7 +124,8 @@ def GetStatus(self, ProfileToken): return self.operator.call("GetStatus", ProfileToken=ProfileToken) def GetConfiguration(self, PTZConfigurationToken): - """Get a specific PTZconfiguration from the device, identified by its reference + """ + Get a specific PTZconfiguration from the device, identified by its reference token or name. The default Position/Translation/Velocity Spaces are introduced to allow NVCs @@ -145,7 +151,8 @@ def GetConfiguration(self, PTZConfigurationToken): ) def GetNodes(self): - """Get the descriptions of the available PTZ Nodes. + """ + Get the descriptions of the available PTZ Nodes. A PTZ-capable device may have multiple PTZ Nodes. The PTZ Nodes may represent mechanical PTZ drivers, uploaded PTZ drivers or digital PTZ drivers. PTZ Nodes @@ -168,7 +175,8 @@ def SetConfiguration(self, PTZConfiguration, ForcePersistence): ) def GetConfigurationOptions(self, ConfigurationToken): - """List supported coordinate systems including their range limitations. + """ + List supported coordinate systems including their range limitations. Therefore, the options MAY differ depending on whether the PTZ Configuration is assigned to a Profile containing a Video Source Configuration. In that case, the @@ -182,7 +190,8 @@ def GetConfigurationOptions(self, ConfigurationToken): ) def GotoHomePosition(self, ProfileToken, Speed=None): - """Operation to move the PTZ device to it's "home" position. + """ + Operation to move the PTZ device to it's "home" position. The operation is supported if the HomeSupported element in the PTZNode is true. """ @@ -191,7 +200,8 @@ def GotoHomePosition(self, ProfileToken, Speed=None): ) def SetHomePosition(self, ProfileToken): - """Operation to save current position as the home position. + """ + Operation to save current position as the home position. The SetHomePosition command returns with a failure if the "home" position is fixed and cannot be overwritten. If the SetHomePosition is successful, it is @@ -200,7 +210,8 @@ def SetHomePosition(self, ProfileToken): return self.operator.call("SetHomePosition", ProfileToken=ProfileToken) def ContinuousMove(self, ProfileToken, Velocity, Timeout=None): - """Operation for continuous Pan/Tilt and Zoom movements. + """ + Operation for continuous Pan/Tilt and Zoom movements. The operation is supported if the PTZNode supports at least one continuous Pan/Tilt or Zoom space. If the space argument is omitted, the default space set @@ -214,7 +225,8 @@ def ContinuousMove(self, ProfileToken, Velocity, Timeout=None): ) def RelativeMove(self, ProfileToken, Translation, Speed=None): - """Operation for Relative Pan/Tilt and Zoom Move. + """ + Operation for Relative Pan/Tilt and Zoom Move. The operation is supported if the PTZNode supports at least one relative Pan/Tilt or Zoom space. @@ -232,7 +244,8 @@ def RelativeMove(self, ProfileToken, Translation, Speed=None): ) def AbsoluteMove(self, ProfileToken, Position, Speed=None): - """Operation to move pan,tilt or zoom to a absolute destination. + """ + Operation to move pan,tilt or zoom to a absolute destination. The speed argument is optional. If an x/y speed value is given it is up to the device to either use the x value as absolute resoluting speed vector or to map x @@ -246,7 +259,8 @@ def AbsoluteMove(self, ProfileToken, Position, Speed=None): def GeoMove( self, ProfileToken, Target, Speed=None, AreaHeight=None, AreaWidth=None ): - """Operation to move pan,tilt or zoom to point to a destination based on the + """ + Operation to move pan,tilt or zoom to point to a destination based on the geolocation of the target. The speed argument is optional. If an x/y speed value is given it is up to the @@ -266,8 +280,9 @@ def GeoMove( ) def Stop(self, ProfileToken, PanTilt=None, Zoom=None): - """Operation to stop ongoing pan, tilt and zoom movements of absolute relative - and continuous type. + """ + Operation to stop ongoing pan, tilt and zoom movements of absolute relative and + continuous type. If no stop argument for pan, tilt or zoom is set, the device will stop all ongoing pan, tilt and zoom movements. @@ -277,8 +292,9 @@ def Stop(self, ProfileToken, PanTilt=None, Zoom=None): ) def SendAuxiliaryCommand(self, ProfileToken, AuxiliaryData): - """Operation to send auxiliary commands to the PTZ device mapped by the PTZNode - in the selected profile. + """ + Operation to send auxiliary commands to the PTZ device mapped by the PTZNode in + the selected profile. The operation is supported if the AuxiliarySupported element of the PTZNode is true @@ -295,7 +311,8 @@ def GetPresetTours(self, ProfileToken): def GetPresetTour(self, ProfileToken, PresetTourToken): """Operation to request a specific PTZ preset tour in the selected media - profile.""" + profile. + """ return self.operator.call( "GetPresetTour", ProfileToken=ProfileToken, PresetTourToken=PresetTourToken ) @@ -320,7 +337,8 @@ def ModifyPresetTour(self, ProfileToken, PresetTour): def OperatePresetTour(self, ProfileToken, PresetTourToken, Operation): """Operation to perform specific operation on the preset tour in selected media - profile.""" + profile. + """ return self.operator.call( "OperatePresetTour", ProfileToken=ProfileToken, @@ -337,7 +355,8 @@ def RemovePresetTour(self, ProfileToken, PresetTourToken): ) def GetCompatibleConfigurations(self, ProfileToken): - """Operation to get all available PTZConfigurations that can be added to the + """ + Operation to get all available PTZConfigurations that can be added to the referenced media profile. A device providing more than one PTZConfiguration or more than one @@ -359,7 +378,8 @@ def MoveAndStartTracking( TargetPosition=None, Speed=None, ): - """Operation to send an an atomic command to the device: move the camera to a + """ + Operation to send an an atomic command to the device: move the camera to a wanted position and then delegate the PTZ control to the tracking algorithm. An existing Speed argument overrides DefaultSpeed of the corresponding PTZ diff --git a/onvif/services/receiver.py b/onvif/services/receiver.py index c002b0e..796442d 100644 --- a/onvif/services/receiver.py +++ b/onvif/services/receiver.py @@ -32,28 +32,32 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the receiver service. + """ + Returns the capabilities of the receiver service. The result is returned in a typed answer. """ return self.operator.call("GetServiceCapabilities") def GetReceivers(self): - """Lists all receivers currently present on a device. + """ + Lists all receivers currently present on a device. This operation is mandatory. """ return self.operator.call("GetReceivers") def GetReceiver(self, ReceiverToken): - """Retrieves the details of a specific receiver. + """ + Retrieves the details of a specific receiver. This operation is mandatory. """ return self.operator.call("GetReceiver", ReceiverToken=ReceiverToken) def CreateReceiver(self, Configuration): - """Creates a new receiver. + """ + Creates a new receiver. This operation is mandatory, although the service may raise a fault if the receiver cannot be created. @@ -61,7 +65,8 @@ def CreateReceiver(self, Configuration): return self.operator.call("CreateReceiver", Configuration=Configuration) def DeleteReceiver(self, ReceiverToken): - """Deletes an existing receiver. + """ + Deletes an existing receiver. A receiver may be deleted only if it is not currently in use; otherwise a fault shall be raised. This operation is mandatory. @@ -69,7 +74,8 @@ def DeleteReceiver(self, ReceiverToken): return self.operator.call("DeleteReceiver", ReceiverToken=ReceiverToken) def ConfigureReceiver(self, ReceiverToken, Configuration): - """Configures an existing receiver. + """ + Configures an existing receiver. This operation is mandatory. """ @@ -80,8 +86,8 @@ def ConfigureReceiver(self, ReceiverToken, Configuration): ) def SetReceiverMode(self, ReceiverToken, Mode): - """Sets the mode of the receiver without affecting the rest of its - configuration. + """ + Sets the mode of the receiver without affecting the rest of its configuration. This operation is mandatory. """ @@ -90,7 +96,8 @@ def SetReceiverMode(self, ReceiverToken, Mode): ) def GetReceiverState(self, ReceiverToken): - """Determines whether the receiver is currently disconnected, connected or + """ + Determines whether the receiver is currently disconnected, connected or attempting to connect. This operation is mandatory. diff --git a/onvif/services/recording.py b/onvif/services/recording.py index bf075d5..966abca 100644 --- a/onvif/services/recording.py +++ b/onvif/services/recording.py @@ -31,14 +31,16 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the recording service. + """ + Returns the capabilities of the recording service. The result is returned in a typed answer. """ return self.operator.call("GetServiceCapabilities") def CreateRecording(self, RecordingConfiguration): - """CreateRecording shall create a new recording. + """ + CreateRecording shall create a new recording. The new recording shall be created with a track for each supported TrackType see Recording Control Spec. @@ -64,7 +66,8 @@ def CreateRecording(self, RecordingConfiguration): ) def DeleteRecording(self, RecordingToken): - """DeleteRecording shall delete a recording object. + """ + DeleteRecording shall delete a recording object. Whenever a recording is deleted, the device shall delete all the tracks that are part of the recording, and it shall delete all the Recording Jobs that record @@ -79,7 +82,8 @@ def DeleteRecording(self, RecordingToken): return self.operator.call("DeleteRecording", RecordingToken=RecordingToken) def GetRecordings(self): - """GetRecordings shall return a description of all the recordings in the device. + """ + GetRecordings shall return a description of all the recordings in the device. This description shall include a list of all the tracks for each recording. """ @@ -95,13 +99,15 @@ def SetRecordingConfiguration(self, RecordingToken, RecordingConfiguration): def GetRecordingConfiguration(self, RecordingToken): """GetRecordingConfiguration shall retrieve the recording configuration for a - recording.""" + recording. + """ return self.operator.call( "GetRecordingConfiguration", RecordingToken=RecordingToken ) def GetRecordingOptions(self, RecordingToken): - """GetRecordingOptions returns information for a recording identified by the + """ + GetRecordingOptions returns information for a recording identified by the RecordingToken. The information includes the number of additional tracks as well as recording @@ -110,7 +116,8 @@ def GetRecordingOptions(self, RecordingToken): return self.operator.call("GetRecordingOptions", RecordingToken=RecordingToken) def CreateTrack(self, RecordingToken, TrackConfiguration): - """This method shall create a new track within a recording. + """ + This method shall create a new track within a recording. This method is optional. It shall be available if the Recording/DynamicTracks capability is TRUE. @@ -125,7 +132,8 @@ def CreateTrack(self, RecordingToken, TrackConfiguration): ) def DeleteTrack(self, RecordingToken, TrackToken): - """DeleteTrack shall remove a track from a recording. + """ + DeleteTrack shall remove a track from a recording. All the data in the track shall be deleted. @@ -138,7 +146,8 @@ def DeleteTrack(self, RecordingToken, TrackToken): def GetTrackConfiguration(self, RecordingToken, TrackToken): """GetTrackConfiguration shall retrieve the configuration for a specific - track.""" + track. + """ return self.operator.call( "GetTrackConfiguration", RecordingToken=RecordingToken, @@ -155,7 +164,8 @@ def SetTrackConfiguration(self, RecordingToken, TrackToken, TrackConfiguration): ) def CreateRecordingJob(self, JobConfiguration): - """CreateRecordingJob shall create a new recording job. + """ + CreateRecordingJob shall create a new recording job. The JobConfiguration returned from CreateRecordingJob shall be identical to the JobConfiguration passed into CreateRecordingJob, except for the ReceiverToken @@ -167,7 +177,8 @@ def CreateRecordingJob(self, JobConfiguration): ) def DeleteRecordingJob(self, JobToken): - """DeleteRecordingJob removes a recording job. + """ + DeleteRecordingJob removes a recording job. It shall also implicitly delete all the receiver objects associated with the recording job that are automatically created using the AutoCreateReceiver field @@ -178,12 +189,13 @@ def DeleteRecordingJob(self, JobToken): def GetRecordingJobs(self): """GetRecordingJobs shall return a list of all the recording jobs in the - device.""" + device. + """ return self.operator.call("GetRecordingJobs") def SetRecordingJobConfiguration(self, JobToken, JobConfiguration): - """SetRecordingJobConfiguration shall change the configuration for a recording - job. + """ + SetRecordingJobConfiguration shall change the configuration for a recording job. SetRecordingJobConfiguration shall implicitly delete any receiver objects that were created automatically if they are no longer used as a result of changing @@ -197,11 +209,13 @@ def SetRecordingJobConfiguration(self, JobToken, JobConfiguration): def GetRecordingJobConfiguration(self, JobToken): """GetRecordingJobConfiguration shall return the current configuration for a - recording job.""" + recording job. + """ return self.operator.call("GetRecordingJobConfiguration", JobToken=JobToken) def SetRecordingJobMode(self, JobToken, Mode): - """SetRecordingJobMode shall change the mode of the recording job. + """ + SetRecordingJobMode shall change the mode of the recording job. Using this method shall be equivalent to retrieving the recording job configuration, and writing it back with a different mode. @@ -209,7 +223,8 @@ def SetRecordingJobMode(self, JobToken, Mode): return self.operator.call("SetRecordingJobMode", JobToken=JobToken, Mode=Mode) def GetRecordingJobState(self, JobToken): - """GetRecordingJobState returns the state of a recording job. + """ + GetRecordingJobState returns the state of a recording job. It includes an aggregated state, and state for each track of the recording job. """ @@ -224,7 +239,8 @@ def ExportRecordedData( EndPoint=None, ): """Exports the selected recordings (from existing recorded data) to the given - storage target based on the requested file format.""" + storage target based on the requested file format. + """ return self.operator.call( "ExportRecordedData", StartPoint=StartPoint, @@ -250,7 +266,8 @@ def OverrideSegmentDuration( self, TargetSegmentDuration, Expiration, RecordingConfiguration ): """Requests a temporary override of the target segment duration for a recording - configuration.""" + configuration. + """ return self.operator.call( "OverrideSegmentDuration", TargetSegmentDuration=TargetSegmentDuration, diff --git a/onvif/services/replay.py b/onvif/services/replay.py index d068115..2622a30 100644 --- a/onvif/services/replay.py +++ b/onvif/services/replay.py @@ -32,15 +32,17 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the replay service. + """ + Returns the capabilities of the replay service. The result is returned in a typed answer. """ return self.operator.call("GetServiceCapabilities") def GetReplayUri(self, StreamSetup, RecordingToken): - """Requests a URI that can be used to initiate playback of a recorded stream - using RTSP as the control protocol. + """ + Requests a URI that can be used to initiate playback of a recorded stream using + RTSP as the control protocol. The URI is valid only as it is specified in the response. A device supporting the Replay Service shall support the GetReplayUri command. @@ -50,14 +52,16 @@ def GetReplayUri(self, StreamSetup, RecordingToken): ) def GetReplayConfiguration(self): - """Returns the current configuration of the replay service. + """ + Returns the current configuration of the replay service. This operation is mandatory. """ return self.operator.call("GetReplayConfiguration") def SetReplayConfiguration(self, Configuration): - """Changes the current configuration of the replay service. + """ + Changes the current configuration of the replay service. This operation is mandatory. """ diff --git a/onvif/services/schedule.py b/onvif/services/schedule.py index 6787d74..0c1b755 100644 --- a/onvif/services/schedule.py +++ b/onvif/services/schedule.py @@ -37,11 +37,13 @@ def GetServiceCapabilities(self): def GetScheduleState(self, Token): """This operation requests the ScheduleState for the schedule instance specified - by the given token.""" + by the given token. + """ return self.operator.call("GetScheduleState", Token=Token) def GetScheduleInfo(self, Token): - """This method returns a list of schedule info items, specified in the request. + """ + This method returns a list of schedule info items, specified in the request. Only found schedules shall be returned, i.e., the returned numbers of elements can differ from the requested element. The device shall ignore tokens it cannot @@ -52,7 +54,8 @@ def GetScheduleInfo(self, Token): return self.operator.call("GetScheduleInfo", Token=Token) def GetScheduleInfoList(self, Limit=None, StartReference=None): - """This operation requests a list of all of ScheduleInfo items provided by the + """ + This operation requests a list of all of ScheduleInfo items provided by the device. A call to this method shall return a StartReference when not all data is @@ -65,7 +68,8 @@ def GetScheduleInfoList(self, Limit=None, StartReference=None): ) def GetSchedules(self, Token): - """This operation returns the specified schedule item matching the given tokens. + """ + This operation returns the specified schedule item matching the given tokens. The device shall ignore tokens it cannot resolve and shall return an empty list if there are no items matching the specified tokens. If the number of requested @@ -74,8 +78,8 @@ def GetSchedules(self, Token): return self.operator.call("GetSchedules", Token=Token) def GetScheduleList(self, Limit=None, StartReference=None): - """This operation requests a list of all of Schedule items provided by the - device. + """ + This operation requests a list of all of Schedule items provided by the device. A call to this method shall return a StartReference when not all data is returned and more data is available. The reference shall be valid for retrieving @@ -87,7 +91,8 @@ def GetScheduleList(self, Limit=None, StartReference=None): ) def CreateSchedule(self, Schedule): - """This operation creates the specified schedule. + """ + This operation creates the specified schedule. The token field of the schedule structure shall be empty, the device shall allocate a token for the schedule. The allocated token shall be returned in the @@ -105,7 +110,8 @@ def ModifySchedule(self, Schedule): return self.operator.call("ModifySchedule", Schedule=Schedule) def DeleteSchedule(self, Token): - """This operation will delete the specified schedule. + """ + This operation will delete the specified schedule. If it is associated with one or more entities some devices may not be able to delete the schedule, and consequently a ReferenceInUse fault shall be generated. @@ -113,8 +119,9 @@ def DeleteSchedule(self, Token): return self.operator.call("DeleteSchedule", Token=Token) def GetSpecialDayGroupInfo(self, Token): - """This operation requests a list of SpecialDayGroupInfo items matching the - given tokens. + """ + This operation requests a list of SpecialDayGroupInfo items matching the given + tokens. The device shall ignore tokens it cannot resolve and shall return an empty list if there are no items matching specified tokens. The device shall not return a @@ -124,8 +131,9 @@ def GetSpecialDayGroupInfo(self, Token): return self.operator.call("GetSpecialDayGroupInfo", Token=Token) def GetSpecialDayGroupInfoList(self, Limit=None, StartReference=None): - """This operation requests a list of all of SpecialDayGroupInfo items provided - by the device. + """ + This operation requests a list of all of SpecialDayGroupInfo items provided by + the device. A call to this method shall return a StartReference when not all data is returned and more data is available. The reference shall be valid for retrieving @@ -138,12 +146,14 @@ def GetSpecialDayGroupInfoList(self, Limit=None, StartReference=None): def GetSpecialDayGroups(self, Token): """This operation returns the specified special day group item matching the - given token.""" + given token. + """ return self.operator.call("GetSpecialDayGroups", Token=Token) def GetSpecialDayGroupList(self, Limit=None, StartReference=None): - """This operation requests a list of all of SpecialDayGroupList items provided - by the device. + """ + This operation requests a list of all of SpecialDayGroupList items provided by + the device. A call to this method shall return a StartReference when not all data is returned and more data is available. The reference shall be valid for retrieving @@ -155,7 +165,8 @@ def GetSpecialDayGroupList(self, Limit=None, StartReference=None): ) def CreateSpecialDayGroup(self, SpecialDayGroup): - """This operation creates the specified special day group. + """ + This operation creates the specified special day group. The token field of the SpecialDayGroup structure shall be empty, the device shall allocate a token for the special day group. The allocated token shall be @@ -177,7 +188,8 @@ def ModifySpecialDayGroup(self, SpecialDayGroup): ) def DeleteSpecialDayGroup(self, Token): - """This method deletes the specified special day group. + """ + This method deletes the specified special day group. If it is associated with one or more schedules some devices may not be able to delete the special day group, and consequently a ReferenceInUse fault must be diff --git a/onvif/services/search.py b/onvif/services/search.py index 0df85a2..8b56724 100644 --- a/onvif/services/search.py +++ b/onvif/services/search.py @@ -31,15 +31,16 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the search service. + """ + Returns the capabilities of the search service. The result is returned in a typed answer. """ return self.operator.call("GetServiceCapabilities") def GetRecordingSummary(self): - """GetRecordingSummary is used to get a summary description of all recorded - data. + """ + GetRecordingSummary is used to get a summary description of all recorded data. This operation is mandatory to support for a device implementing the recording search service. @@ -47,7 +48,8 @@ def GetRecordingSummary(self): return self.operator.call("GetRecordingSummary") def GetRecordingInformation(self, RecordingToken): - """Returns information about a single Recording specified by a RecordingToken. + """ + Returns information about a single Recording specified by a RecordingToken. This operation is mandatory to support for a device implementing the recording search service. @@ -57,8 +59,9 @@ def GetRecordingInformation(self, RecordingToken): ) def GetMediaAttributes(self, Time, RecordingTokens=None): - """Returns a set of media attributes for all tracks of the specified recordings - at a specified point in time. + """ + Returns a set of media attributes for all tracks of the specified recordings at + a specified point in time. Clients using this operation shall be able to use it as a non blocking operation. A device shall set the starttime and endtime of the MediaAttributes @@ -71,8 +74,9 @@ def GetMediaAttributes(self, Time, RecordingTokens=None): ) def FindRecordings(self, Scope, KeepAliveTime, MaxMatches=None): - """FindRecordings starts a search session, looking for recordings that matches - the scope (See 20.2.4) defined in the request. + """ + FindRecordings starts a search session, looking for recordings that matches the + scope (See 20.2.4) defined in the request. Results from the search are acquired using the GetRecordingSearchResults request, specifying the search token returned from this request. The device @@ -98,8 +102,9 @@ def FindRecordings(self, Scope, KeepAliveTime, MaxMatches=None): def GetRecordingSearchResults( self, SearchToken, MinResults=None, MaxResults=None, WaitTime=None ): - """GetRecordingSearchResults acquires the results from a recording search - session previously initiated by a FindRecordings operation. + """ + GetRecordingSearchResults acquires the results from a recording search session + previously initiated by a FindRecordings operation. The response shall not include results already returned in previous requests for the same session. If MaxResults is specified, the response shall not contain @@ -135,8 +140,9 @@ def FindEvents( EndPoint=None, MaxMatches=None, ): - """FindEvents starts a search session, looking for recording events (in the - scope that matches the search filter defined in the request. + """ + FindEvents starts a search session, looking for recording events (in the scope + that matches the search filter defined in the request. Results from the search are acquired using the GetEventSearchResults request, specifying the search token returned from this request. @@ -167,8 +173,9 @@ def FindEvents( def GetEventSearchResults( self, SearchToken, MinResults=None, MaxResults=None, WaitTime=None ): - """GetEventSearchResults acquires the results from a recording event search - session previously initiated by a FindEvents operation. + """ + GetEventSearchResults acquires the results from a recording event search session + previously initiated by a FindEvents operation. The response shall not include results already returned in previous requests for the same session. If MaxResults is specified, the response shall not contain @@ -201,8 +208,9 @@ def FindPTZPosition( EndPoint=None, MaxMatches=None, ): - """FindPTZPosition starts a search session, looking for ptz positions in the - scope (See 20.2.4) that matches the search filter defined in the request. + """ + FindPTZPosition starts a search session, looking for ptz positions in the scope + (See 20.2.4) that matches the search filter defined in the request. Results from the search are acquired using the GetPTZPositionSearchResults request, specifying the search token returned from this request. @@ -231,7 +239,8 @@ def FindPTZPosition( def GetPTZPositionSearchResults( self, SearchToken, MinResults=None, MaxResults=None, WaitTime=None ): - """GetPTZPositionSearchResults acquires the results from a ptz position search + """ + GetPTZPositionSearchResults acquires the results from a ptz position search session previously initiated by a FindPTZPosition operation. The response shall not include results already returned in previous requests for @@ -257,15 +266,17 @@ def GetPTZPositionSearchResults( ) def GetSearchState(self, SearchToken): - """GetSearchState returns the current state of the specified search session. + """ + GetSearchState returns the current state of the specified search session. This command is deprecated . """ return self.operator.call("GetSearchState", SearchToken=SearchToken) def EndSearch(self, SearchToken): - """EndSearch stops and ongoing search session, causing any blocking result - request to return and the SearchToken to become invalid. + """ + EndSearch stops and ongoing search session, causing any blocking result request + to return and the SearchToken to become invalid. If the search was interrupted before completion, the point in time that the search had reached shall be returned. If the search had not yet begun, the @@ -286,7 +297,8 @@ def FindMetadata( EndPoint=None, MaxMatches=None, ): - """FindMetadata starts a search session, looking for metadata in the scope (See + """ + FindMetadata starts a search session, looking for metadata in the scope (See 20.2.4) that matches the search filter defined in the request. Results from the search are acquired using the GetMetadataSearchResults request, @@ -317,7 +329,8 @@ def FindMetadata( def GetMetadataSearchResults( self, SearchToken, MinResults=None, MaxResults=None, WaitTime=None ): - """GetMetadataSearchResults acquires the results from a recording search session + """ + GetMetadataSearchResults acquires the results from a recording search session previously initiated by a FindMetadata operation. The response shall not include results already returned in previous requests for @@ -356,8 +369,7 @@ def SearchImageByNL( """ - Starts a natural language search session and specifies the search - parameters. + Starts a natural language search session and specifies the search parameters. """ return self.operator.call( "SearchImageByNL", diff --git a/onvif/services/security/advancedsecurity.py b/onvif/services/security/advancedsecurity.py index 9cf08d4..665c2db 100644 --- a/onvif/services/security/advancedsecurity.py +++ b/onvif/services/security/advancedsecurity.py @@ -31,7 +31,8 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the security configuration service. + """ + Returns the capabilities of the security configuration service. The result is returned in a typed answer. """ diff --git a/onvif/services/security/authorizationserver.py b/onvif/services/security/authorizationserver.py index b7edad3..47bc987 100644 --- a/onvif/services/security/authorizationserver.py +++ b/onvif/services/security/authorizationserver.py @@ -31,11 +31,13 @@ def __init__(self, xaddr=None, **kwargs): def GetAuthorizationServerConfigurations(self, Token=None): """This operation lists all existing authorization server configurations for the - device.""" + device. + """ return self.operator.call("GetAuthorizationServerConfigurations", Token=Token) def CreateAuthorizationServerConfiguration(self, Configuration): - """This operation creates a new authorization server configuration. + """ + This operation creates a new authorization server configuration. The configuration data shall be created in the device and shall be persistent (remain after reboot). @@ -52,5 +54,6 @@ def SetAuthorizationServerConfiguration(self, Configuration): def DeleteAuthorizationServerConfiguration(self, Token): """This operation deletes the given authorization server configuration and - configuration change shall always be persistent.""" + configuration change shall always be persistent. + """ return self.operator.call("DeleteAuthorizationServerConfiguration", Token=Token) diff --git a/onvif/services/security/dot1x.py b/onvif/services/security/dot1x.py index abea8d2..bd7d008 100644 --- a/onvif/services/security/dot1x.py +++ b/onvif/services/security/dot1x.py @@ -30,7 +30,8 @@ def __init__(self, xaddr=None, **kwargs): ) def AddDot1XConfiguration(self, Dot1XConfiguration): - """This operation adds an IEEE 802.1X configuration to the device. + """ + This operation adds an IEEE 802.1X configuration to the device. Configurations are uniquely identified using IEEE 802.1X configuration IDs. The device shall ignore Dot1XID in the request, if present, and shall generate a @@ -62,8 +63,9 @@ def AddDot1XConfiguration(self, Dot1XConfiguration): ) def GetAllDot1XConfigurations(self): - """This operation returns details of all IEEE 802.1X configurations that are on - the device. + """ + This operation returns details of all IEEE 802.1X configurations that are on the + device. This operation may be used, e.g., if a client lost track of which IEEE 802.1X configurations are present on the device. If no IEEE 802.1X configurations exist @@ -74,7 +76,8 @@ def GetAllDot1XConfigurations(self): return self.operator.call("GetAllDot1XConfigurations") def GetDot1XConfiguration(self, Dot1XID): - """This operation returns details of a specific IEEE 802.1X configuration on the + """ + This operation returns details of a specific IEEE 802.1X configuration on the device. If the device cannot process the provided IEEE 802.1X configuration ID, the @@ -85,7 +88,8 @@ def GetDot1XConfiguration(self, Dot1XID): return self.operator.call("GetDot1XConfiguration", Dot1XID=Dot1XID) def DeleteDot1XConfiguration(self, Dot1XID): - """This operation deletes an IEEE 802.1X configuration from the device. + """ + This operation deletes an IEEE 802.1X configuration from the device. If the device cannot process the provided IEEE 802.1X configuration ID, the device shall produce a Dot1XConfigurationID fault. If a reference exists for the @@ -98,8 +102,9 @@ def DeleteDot1XConfiguration(self, Dot1XID): return self.operator.call("DeleteDot1XConfiguration", Dot1XID=Dot1XID) def SetNetworkInterfaceDot1XConfiguration(self, token, Dot1XID): - """This operation binds an IEEE 802.1X configuration to a network interface on - the device. + """ + This operation binds an IEEE 802.1X configuration to a network interface on the + device. This operation shall either create a new binding or replace an existing binding. On failure when an existing binding already exists, the existing binding shall @@ -124,7 +129,8 @@ def SetNetworkInterfaceDot1XConfiguration(self, token, Dot1XID): ) def GetNetworkInterfaceDot1XConfiguration(self, token): - """This operation returns the IEEE 802.1X ID and configuration associated with a + """ + This operation returns the IEEE 802.1X ID and configuration associated with a network interface on the device. If there is no IEEE 802.1X configuration associated with the specified network @@ -140,8 +146,9 @@ def GetNetworkInterfaceDot1XConfiguration(self, token): return self.operator.call("GetNetworkInterfaceDot1XConfiguration", token=token) def DeleteNetworkInterfaceDot1XConfiguration(self, token): - """This operation unbinds the IEEE 802.1X configuration associated with a - network interface on the device. + """ + This operation unbinds the IEEE 802.1X configuration associated with a network + interface on the device. If there is no IEEE 802.1X configuration associated with the specified network interface, then the operation does nothing. The Device Management diff --git a/onvif/services/security/jwt.py b/onvif/services/security/jwt.py index 6aea843..c21c534 100644 --- a/onvif/services/security/jwt.py +++ b/onvif/services/security/jwt.py @@ -31,10 +31,12 @@ def __init__(self, xaddr=None, **kwargs): def GetJWTConfiguration(self): """This operation returns the parameters of the JWT authorization used by the - device.""" + device. + """ return self.operator.call("GetJWTConfiguration") def SetJWTConfiguration(self, Configuration): """This operation sets the parameters of the JWT authorization used by the - device.""" + device. + """ return self.operator.call("SetJWTConfiguration", Configuration=Configuration) diff --git a/onvif/services/security/keystore.py b/onvif/services/security/keystore.py index 0ce1f1d..2681013 100644 --- a/onvif/services/security/keystore.py +++ b/onvif/services/security/keystore.py @@ -30,7 +30,8 @@ def __init__(self, xaddr=None, **kwargs): ) def CreateRSAKeyPair(self, KeyLength, Alias=None): - """This operation triggers the asynchronous generation of an RSA key pair of a + """ + This operation triggers the asynchronous generation of an RSA key pair of a particular key length (specified as the number of bits) as specified in [RFC 3447], with a suitable key generation mechanism on the device. @@ -58,8 +59,9 @@ def CreateRSAKeyPair(self, KeyLength, Alias=None): return self.operator.call("CreateRSAKeyPair", KeyLength=KeyLength, Alias=Alias) def CreateECCKeyPair(self, EllipticCurve, Alias=None): - """This operation triggers the asynchronous generation of an ECC key pair using - a particular elliptic curve as specified in [RFC 8422], with a suitable key + """ + This operation triggers the asynchronous generation of an ECC key pair using a + particular elliptic curve as specified in [RFC 8422], with a suitable key generation mechanism on the device. Keys, especially ECC key pairs, are uniquely identified using key IDs. @@ -94,7 +96,8 @@ def UploadKeyPairInPKCS8( EncryptionPassphraseID=None, EncryptionPassphrase=None, ): - """Deprecated method for uploading a key pair in a PKCS#8 data structure as + """ + Deprecated method for uploading a key pair in a PKCS#8 data structure as specified in [RFC 5958, RFC 5959]. If an encryption passphrase ID is supplied in the request, the device shall @@ -124,9 +127,10 @@ def UploadCertificateWithPrivateKeyInPKCS12( EncryptionPassphraseID=None, Passphrase=None, ): - """This operation uploads a certification path consisting of X.509 certificates - as specified by [RFC 5280] in DER encoding along with a private key to a - device’s keystore. + """ + This operation uploads a certification path consisting of X.509 certificates as + specified by [RFC 5280] in DER encoding along with a private key to a device’s + keystore. Certificates and private key are supplied in the form of a PKCS#12 file as specified in [PKCS#12]. @@ -167,7 +171,8 @@ def UploadCertificateWithPrivateKeyInPKCS12( ) def GetKeyStatus(self, KeyID): - """This operation returns the status of a key. + """ + This operation returns the status of a key. Keys are uniquely identified using key IDs. If no key is stored under the requested key ID in the keystore, an InvalidKeyID fault is produced. Otherwise, @@ -176,7 +181,8 @@ def GetKeyStatus(self, KeyID): return self.operator.call("GetKeyStatus", KeyID=KeyID) def GetPrivateKeyStatus(self, KeyID): - """This operation returns whether a key pair contains a private key. + """ + This operation returns whether a key pair contains a private key. Keys are uniquely identified using key IDs. If no key is stored under the requested key ID in the keystore or the key identified by the requested key ID @@ -187,7 +193,8 @@ def GetPrivateKeyStatus(self, KeyID): return self.operator.call("GetPrivateKeyStatus", KeyID=KeyID) def GetAllKeys(self): - """This operation returns information about all keys that are stored in the + """ + This operation returns information about all keys that are stored in the device’s keystore. This operation may be used, e.g., if a client lost track of which keys are @@ -197,7 +204,8 @@ def GetAllKeys(self): return self.operator.call("GetAllKeys") def DeleteKey(self, KeyID): - """This operation deletes a key from the device’s keystore. + """ + This operation deletes a key from the device’s keystore. Keys are uniquely identified using key IDs. If no key is stored under the requested key ID in the keystore, a device shall produce an InvalidArgVal fault. @@ -212,7 +220,8 @@ def DeleteKey(self, KeyID): return self.operator.call("DeleteKey", KeyID=KeyID) def CreatePKCS10CSR(self, Subject, KeyID, SignatureAlgorithm, CSRAttribute=None): - """This operation generates a DER-encoded PKCS#10 v1.7 certification request + """ + This operation generates a DER-encoded PKCS#10 v1.7 certification request (sometimes also called certificate signing request or CSR) as specified in RFC 2986 for a public key on the device. @@ -252,7 +261,8 @@ def CreateSelfSignedCertificate( notValidAfter=None, Extension=None, ): - """This operation generates for a public key on the device a self-signed X.509 + """ + This operation generates for a public key on the device a self-signed X.509 certificate that complies to RFC 5280. The X509Version parameter specifies the version of X.509 that the generated @@ -297,7 +307,8 @@ def CreateSelfSignedCertificate( def UploadCertificate( self, Certificate, Alias=None, KeyAlias=None, PrivateKeyRequired=None ): - """This operation uploads an X.509 certificate as specified by [RFC 5280] in DER + """ + This operation uploads an X.509 certificate as specified by [RFC 5280] in DER encoding and the public key in the certificate to a device’s keystore. A device that supports this command shall be able to handle X.509v3 certificates @@ -359,7 +370,8 @@ def UploadCertificate( ) def GetCertificate(self, CertificateID): - """This operation returns a specific certificate from the device’s keystore. + """ + This operation returns a specific certificate from the device’s keystore. Certificates are uniquely identified using certificate IDs. If no certificate is stored under the requested certificate ID in the keystore, an InvalidArgVal @@ -369,7 +381,8 @@ def GetCertificate(self, CertificateID): return self.operator.call("GetCertificate", CertificateID=CertificateID) def GetAllCertificates(self): - """This operation returns the IDs of all certificates that are stored in the + """ + This operation returns the IDs of all certificates that are stored in the device’s keystore. This operation may be used, e.g., if a client lost track of which certificates @@ -379,7 +392,8 @@ def GetAllCertificates(self): return self.operator.call("GetAllCertificates") def DeleteCertificate(self, CertificateID): - """This operation deletes a certificate from the device’s keystore. + """ + This operation deletes a certificate from the device’s keystore. The operation shall not delete the public key that is contained in the certificate from the keystore. Certificates are uniquely identified using @@ -394,7 +408,8 @@ def DeleteCertificate(self, CertificateID): return self.operator.call("DeleteCertificate", CertificateID=CertificateID) def CreateCertificationPath(self, CertificateIDs, Alias=None): - """This operation creates a sequence of certificates that may be used, e.g., for + """ + This operation creates a sequence of certificates that may be used, e.g., for certification path validation or for TLS server authentication. Certification paths are uniquely identified using certification path IDs. @@ -417,8 +432,8 @@ def CreateCertificationPath(self, CertificateIDs, Alias=None): ) def GetCertificationPath(self, CertificationPathID): - """This operation returns a specific certification path from the device’s - keystore. + """ + This operation returns a specific certification path from the device’s keystore. Certification paths are uniquely identified using certification path IDs. If no certification path is stored under the requested ID in the keystore, an @@ -429,8 +444,9 @@ def GetCertificationPath(self, CertificationPathID): ) def GetAllCertificationPaths(self): - """This operation returns the IDs of all certification paths that are stored in - the device’s keystore. + """ + This operation returns the IDs of all certification paths that are stored in the + device’s keystore. This operation may be used, e.g., if a client lost track of which certificates are present on the device. If no certification path is stored on the device, an @@ -447,7 +463,8 @@ def SetCertificationPath(self, CertificationPathID, CertificationPath): ) def DeleteCertificationPath(self, CertificationPathID): - """This operation deletes a certification path from the device’s keystore. + """ + This operation deletes a certification path from the device’s keystore. This operation shall not delete the certificates that are referenced by the certification path. Certification paths are uniquely identified using @@ -472,8 +489,9 @@ def UploadPassphrase(self, Passphrase, PassphraseAlias=None): ) def GetAllPassphrases(self): - """This operation returns information about all passphrases that are stored in - the keystore of the device. + """ + This operation returns information about all passphrases that are stored in the + keystore of the device. This operation may be used, e.g., if a client lost track of which passphrases are present on the device. If no passphrase is stored on the device, the device @@ -486,8 +504,9 @@ def DeletePassphrase(self, PassphraseID): return self.operator.call("DeletePassphrase", PassphraseID=PassphraseID) def UploadCRL(self, Crl, Alias=None, anyParameters=None): - """This operation uploads a certificate revocation list (CRL) as specified in - [RFC 5280] to the keystore on the device. + """ + This operation uploads a certificate revocation list (CRL) as specified in [RFC + 5280] to the keystore on the device. If the device does not have enough storage space to store the CRL to be uploaded, the device shall produce a MaximumNumberOfCRLsReached fault and shall @@ -502,7 +521,8 @@ def UploadCRL(self, Crl, Alias=None, anyParameters=None): ) def GetCRL(self, CrlID): - """This operation returns a specific certificate revocation list (CRL) from the + """ + This operation returns a specific certificate revocation list (CRL) from the keystore on the device. Certification revocation lists are uniquely identified using CRLIDs. If no CRL @@ -511,8 +531,9 @@ def GetCRL(self, CrlID): return self.operator.call("GetCRL", CrlID=CrlID) def GetAllCRLs(self): - """This operation returns all certificate revocation lists (CRLs) that are - stored in the keystore on the device. + """ + This operation returns all certificate revocation lists (CRLs) that are stored + in the keystore on the device. If no certificate revocation list is stored in the device’s keystore, an empty list is returned. @@ -520,8 +541,9 @@ def GetAllCRLs(self): return self.operator.call("GetAllCRLs") def DeleteCRL(self, CrlID): - """This operation deletes a certificate revocation list (CRL) from the keystore - on the device. + """ + This operation deletes a certificate revocation list (CRL) from the keystore on + the device. Certification revocation lists are uniquely identified using CRLIDs. If no CRL is stored under the requested CRLID, the device shall produce a CRLID fault. If @@ -534,7 +556,8 @@ def DeleteCRL(self, CrlID): def CreateCertPathValidationPolicy( self, Parameters, TrustAnchor, Alias=None, anyParameters=None ): - """This operation creates a certification path validation policy. + """ + This operation creates a certification path validation policy. Certification path validation policies are uniquely identified using certification path validation policy IDs. The device shall generate a new @@ -562,8 +585,9 @@ def CreateCertPathValidationPolicy( ) def GetCertPathValidationPolicy(self, CertPathValidationPolicyID): - """This operation returns a certification path validation policy from the - keystore on the device. + """ + This operation returns a certification path validation policy from the keystore + on the device. Certification path validation policies are uniquely identified using certification path validation policy IDs. If no certification path validation @@ -576,7 +600,8 @@ def GetCertPathValidationPolicy(self, CertPathValidationPolicyID): ) def GetAllCertPathValidationPolicies(self): - """This operation returns all certification path validation policies that are + """ + This operation returns all certification path validation policies that are stored in the keystore on the device. If no certification path validation policy is stored in the device’s keystore, @@ -588,7 +613,8 @@ def SetCertPathValidationPolicy( self, CertPathValidationPolicy, CertPathValidationPolicyID=None ): """This operation allows to modify an existing certification path validation - policy.""" + policy. + """ return self.operator.call( "SetCertPathValidationPolicy", CertPathValidationPolicyID=CertPathValidationPolicyID, @@ -596,8 +622,9 @@ def SetCertPathValidationPolicy( ) def DeleteCertPathValidationPolicy(self, CertPathValidationPolicyID): - """This operation deletes a certification path validation policy from the - keystore on the device. + """ + This operation deletes a certification path validation policy from the keystore + on the device. Certification path validation policies are uniquely identified using certification path validation policy IDs. If no certification path validation diff --git a/onvif/services/security/mediasigning.py b/onvif/services/security/mediasigning.py index 987b36a..5f4aee6 100644 --- a/onvif/services/security/mediasigning.py +++ b/onvif/services/security/mediasigning.py @@ -32,12 +32,13 @@ def __init__(self, xaddr=None, **kwargs): ) def AddMediaSigningCertificateAssignment(self, CertificationPathID): - """This operation assigns certification path (certificate chain) to use for - media signing, replacing the one that is provisioned during factory production. + """ + This operation assigns certification path (certificate chain) to use for media + signing, replacing the one that is provisioned during factory production. The leaf certificate in the chain and its associated private key shall be used - for signing media as described in the [Media Signing Spec]. This key - and certificate is referred to as user provisioned key and certificate in that + for signing media as described in the [Media Signing Spec]. This key and + certificate is referred to as user provisioned key and certificate in that specification. If this operation is called when there is already a user provisioned @@ -53,8 +54,9 @@ def AddMediaSigningCertificateAssignment(self, CertificationPathID): ) def RemoveMediaSigningCertificateAssignment(self, CertificationPathID): - """This operation removes a certificate assignment (including certification - path) on the device that has been added by AddMediaSigningCertificateAssignment. + """ + This operation removes a certificate assignment (including certification path) + on the device that has been added by AddMediaSigningCertificateAssignment. The factory provisioned certification path cannot be removed. @@ -70,8 +72,9 @@ def RemoveMediaSigningCertificateAssignment(self, CertificationPathID): ) def GetAssignedMediaSigningCertificates(self): - """This operation returns the IDs of the certification paths that are assigned - for media signing on the device. + """ + This operation returns the IDs of the certification paths that are assigned for + media signing on the device. This operation will always return the factory provisioned certification path and can additionally return a certification path that has been added by diff --git a/onvif/services/security/tlsserver.py b/onvif/services/security/tlsserver.py index 9e86a9b..977997d 100644 --- a/onvif/services/security/tlsserver.py +++ b/onvif/services/security/tlsserver.py @@ -30,11 +30,12 @@ def __init__(self, xaddr=None, **kwargs): ) def AddServerCertificateAssignment(self, CertificationPathID): - """This operation assigns a key pair and certificate along with a certification + """ + This operation assigns a key pair and certificate along with a certification path (certificate chain) to the TLS server on the device. - The TLS server shall use this information for key exchange during the TLS handshake, - particularly for constructing server certificate messages. + The TLS server shall use this information for key exchange during the TLS + handshake, particularly for constructing server certificate messages. Certification paths are identified by their certification path IDs in the keystore. The first certificate in the certification path must be the TLS server @@ -46,12 +47,13 @@ def AddServerCertificateAssignment(self, CertificationPathID): If a device chooses to perform a TLS key exchange based on the supplied certification path, it shall use the key pair that is associated with the server - certificate for key exchange and transmit the certification path to TLS clients as-is. - In order to use the server certificate during the TLS handshake, the corresponding - private key is required. Therefore, if the key pair that is associated with the server - certificate, i.e., the first certificate in the certification path, does not have an - associated private key, the NoPrivateKey fault is produced and the certification path - is not associated to the TLS server. + certificate for key exchange and transmit the certification path to TLS clients + as-is. In order to use the server certificate during the TLS handshake, the + corresponding private key is required. Therefore, if the key pair that is + associated with the server certificate, i.e., the first certificate in the + certification path, does not have an associated private key, the NoPrivateKey + fault is produced and the certification path is not associated to the TLS + server. A TLS server may present different certification paths to different clients during the TLS handshake instead of presenting the same certification path to @@ -68,7 +70,8 @@ def AddServerCertificateAssignment(self, CertificationPathID): ) def RemoveServerCertificateAssignment(self, CertificationPathID): - """This operation removes a key pair and certificate assignment (including + """ + This operation removes a key pair and certificate assignment (including certification path) to the TLS server on the device. Certification paths are identified using certification path IDs. If the supplied @@ -82,9 +85,10 @@ def RemoveServerCertificateAssignment(self, CertificationPathID): def ReplaceServerCertificateAssignment( self, OldCertificationPathID, NewCertificationPathID ): - """This operation replaces an existing key pair and certificate assignment to - the TLS server on the device by a new key pair and certificate assignment - (including certification paths). + """ + This operation replaces an existing key pair and certificate assignment to the + TLS server on the device by a new key pair and certificate assignment (including + certification paths). After the replacement, the TLS server shall use the new certificate and certification path exactly in those cases in which it would have used the old @@ -123,7 +127,8 @@ def ReplaceServerCertificateAssignment( ) def GetAssignedServerCertificates(self): - """This operation returns the IDs of all key pairs and certificates (including + """ + This operation returns the IDs of all key pairs and certificates (including certification paths) that are assigned to the TLS server on the device. This operation may be used, e.g., if a client lost track of the certification @@ -133,12 +138,13 @@ def GetAssignedServerCertificates(self): return self.operator.call("GetAssignedServerCertificates") def SetEnabledTLSVersions(self, Versions): - """This operation sets the version(s) of TLS which the device shall use. + """ + This operation sets the version(s) of TLS which the device shall use. Valid values are taken from the TLSServerSupported capability. A client - initiates a TLS session by sending a ClientHello with the highest TLS version - it supports. This suggests to the server that the client can accept any TLS - version up to and including that version. + initiates a TLS session by sending a ClientHello with the highest TLS version it + supports. This suggests to the server that the client can accept any TLS version + up to and including that version. The server then chooses the TLS version to use. This is generally the highest TLS version the server supports that is within the range of the client. For @@ -162,11 +168,13 @@ def SetEnabledTLSVersions(self, Versions): def GetEnabledTLSVersions(self): """This operation retrieves the version(s) of TLS which are currently enabled on - the device.""" + the device. + """ return self.operator.call("GetEnabledTLSVersions") def SetClientAuthenticationRequired(self, clientAuthenticationRequired): - """This operation activates or deactivates TLS client authentication for the TLS + """ + This operation activates or deactivates TLS client authentication for the TLS server on the device. The TLS server on the device shall require client authentication if and only if @@ -187,8 +195,9 @@ def GetClientAuthenticationRequired(self): return self.operator.call("GetClientAuthenticationRequired") def SetCnMapsToUser(self, cnMapsToUser): - """This operation enables or disables mapping of the Common Name present in the - TLS client certificate to an existing user name in the device. + """ + This operation enables or disables mapping of the Common Name present in the TLS + client certificate to an existing user name in the device. The TLS server on the device shall perform mapping if parameter clientAuthenticationRequired is set to true. @@ -200,8 +209,9 @@ def GetCnMapsToUser(self): return self.operator.call("GetCnMapsToUser") def AddCertPathValidationPolicyAssignment(self, CertPathValidationPolicyID): - """This operation assigns a certification path validation policy to the TLS - server on the device. + """ + This operation assigns a certification path validation policy to the TLS server + on the device. The TLS server shall enforce the policy when authenticating TLS clients and consider a client authentic if and only if the algorithm returns valid. If no @@ -221,7 +231,8 @@ def AddCertPathValidationPolicyAssignment(self, CertPathValidationPolicyID): ) def RemoveCertPathValidationPolicyAssignment(self, CertPathValidationPolicyID): - """This operation removes a certification path validation policy assignment from + """ + This operation removes a certification path validation policy assignment from the TLS server on the device. If the certification path validation policy identified by the requested @@ -236,8 +247,9 @@ def RemoveCertPathValidationPolicyAssignment(self, CertPathValidationPolicyID): def ReplaceCertPathValidationPolicyAssignment( self, OldCertPathValidationPolicyID, NewCertPathValidationPolicyID ): - """This operation replaces a certification path validation policy assignment to - the TLS server on the device with another certification path validation policy + """ + This operation replaces a certification path validation policy assignment to the + TLS server on the device with another certification path validation policy assignment. If the certification path validation policy identified by the requested @@ -258,5 +270,6 @@ def ReplaceCertPathValidationPolicyAssignment( def GetAssignedCertPathValidationPolicies(self): """This operation returns the IDs of all certification path validation policies - that are assigned to the TLS server on the device.""" + that are assigned to the TLS server on the device. + """ return self.operator.call("GetAssignedCertPathValidationPolicies") diff --git a/onvif/services/thermal.py b/onvif/services/thermal.py index 214e039..304f5b4 100644 --- a/onvif/services/thermal.py +++ b/onvif/services/thermal.py @@ -31,14 +31,16 @@ def __init__(self, xaddr=None, **kwargs): ) def GetServiceCapabilities(self): - """Returns the capabilities of the thermal service. + """ + Returns the capabilities of the thermal service. The result is returned in a typed answer. """ return self.operator.call("GetServiceCapabilities") def GetConfigurationOptions(self, VideoSourceToken): - """Gets the valid ranges for the Thermal parameters that have device specific + """ + Gets the valid ranges for the Thermal parameters that have device specific ranges. This command is mandatory for all devices implementing the Thermal service. The @@ -66,7 +68,8 @@ def SetConfiguration(self, VideoSourceToken, Configuration): ) def GetRadiometryConfigurationOptions(self, VideoSourceToken): - """Gets the valid ranges for the Radiometry parameters that have device specific + """ + Gets the valid ranges for the Radiometry parameters that have device specific ranges. The command shall return all supported parameters and their ranges, such that diff --git a/onvif/services/uplink.py b/onvif/services/uplink.py index f3f17f6..d87e3a4 100644 --- a/onvif/services/uplink.py +++ b/onvif/services/uplink.py @@ -35,7 +35,8 @@ def GetServiceCapabilities(self): return self.operator.call("GetServiceCapabilities") def GetUplinks(self): - """A device supporting uplinks shall support this command to retrieve the + """ + A device supporting uplinks shall support this command to retrieve the configured uplink configurations. The Status field shall signal whether a connection is Offline, Connecting or @@ -44,7 +45,8 @@ def GetUplinks(self): return self.operator.call("GetUplinks") def SetUplink(self, Configuration): - """A device supporting uplinks shall support this command to add or modify an + """ + A device supporting uplinks shall support this command to add or modify an uplink configuration. The Status property of the UplinkConfiguration shall be ignored by the device. A @@ -55,5 +57,6 @@ def SetUplink(self, Configuration): def DeleteUplink(self, RemoteAddress): """A device supporting uplinks shall support this command to remove an uplink - configuration.""" + configuration. + """ return self.operator.call("DeleteUplink", RemoteAddress=RemoteAddress) diff --git a/onvif/utils/discovery.py b/onvif/utils/discovery.py index fdd21a9..e2d73a6 100644 --- a/onvif/utils/discovery.py +++ b/onvif/utils/discovery.py @@ -25,10 +25,8 @@ class ONVIFDiscovery: """ - - - - + Discover ONVIF devices using the WS-Discovery protocol. @@ -82,7 +80,8 @@ def __init__( timeout: int = 4, interface: str | None = None, ): - """Initialize ONVIF Discovery. + """ + Initialize ONVIF Discovery. Args: timeout (int): Discovery timeout in seconds @@ -94,8 +93,7 @@ def __init__( def get_local_ip(self) -> str: """ - - + Get local network interface IP address. @@ -139,8 +137,7 @@ def discover( self, prefer_https: bool = False, search: str | None = None ) -> list[dict[str, Any]]: """ - - + Discover ONVIF devices on the network. @@ -263,7 +260,8 @@ def discover( def _filter_devices( self, devices: list[dict[str, Any]], search_term: str ) -> list[dict[str, Any]]: - """Filter devices based on search term in types or scopes. + """ + Filter devices based on search term in types or scopes. Args: devices (list[dict[str, Any]]): List of discovered devices @@ -297,7 +295,8 @@ def _filter_devices( return filtered def _process_single_device(self, device: dict[str, Any]) -> dict[str, Any]: - """Enrich a single discovered device with unauthenticated information. + """ + Enrich a single discovered device with unauthenticated information. Connects to the discovered device without authentication and attempts to retrieve information that is available without credentials, including the @@ -384,7 +383,8 @@ def _process_single_device(self, device: dict[str, Any]) -> dict[str, Any]: def _process_device( self, discovered_devices: list[dict[str, Any]] ) -> list[dict[str, Any]]: - """Enrich discovered devices with unauthenticated device information. + """ + Enrich discovered devices with unauthenticated device information. Connects to each discovered device without authentication and processes devices concurrently using a thread pool. Information that is available @@ -419,7 +419,8 @@ def _process_device( def _parse_single_response( self, xml_data: str, prefer_https: bool = False ) -> dict[str, Any] | None: - """Parse a single WS-Discovery response. + """ + Parse a single WS-Discovery response. Args: xml_data (str): Raw XML response data @@ -497,7 +498,8 @@ def _parse_single_response( def _parse_responses( self, responses: list[dict[str, str]], prefer_https: bool = False ) -> list[dict[str, Any]]: - """Parse WS-Discovery responses into device information. + """ + Parse WS-Discovery responses into device information. Args: responses (list[dict[str, str]]): List of raw XML responses @@ -528,7 +530,8 @@ def _parse_responses( def _parse_xaddr( self, device_info: dict[str, Any], prefer_https: bool = False ) -> None: - """Parse XAddr to extract host, port, and protocol. + """ + Parse XAddr to extract host, port, and protocol. Args: device_info (dict[str, Any]): Device information dictionary to update diff --git a/onvif/utils/error_handlers.py b/onvif/utils/error_handlers.py index dfcee23..84a6bd1 100644 --- a/onvif/utils/error_handlers.py +++ b/onvif/utils/error_handlers.py @@ -1,8 +1,6 @@ """ - - - - + Error handling utilities for ONVIF operations. diff --git a/onvif/utils/exceptions.py b/onvif/utils/exceptions.py index 6dbe236..c5c436b 100644 --- a/onvif/utils/exceptions.py +++ b/onvif/utils/exceptions.py @@ -10,8 +10,7 @@ class ONVIFOperationException(Exception): # pylint: disable=line-too-long """ - - + Enhanced exception wrapper for ONVIF operation failures. @@ -89,6 +88,7 @@ class ONVIFOperationException(Exception): - `zeep.exceptions.Fault`: Base SOAP fault exception - `requests.exceptions.RequestException`: Base HTTP error """ + # pylint: enable=line-too-long def __init__(self, operation: str, original_exception: Exception): diff --git a/onvif/utils/plugins.py b/onvif/utils/plugins.py index e2e88cf..2b78a79 100644 --- a/onvif/utils/plugins.py +++ b/onvif/utils/plugins.py @@ -1,4 +1,5 @@ -"""Auxiliary custom Zeep plugins outside the core scope. +""" +Auxiliary custom Zeep plugins outside the core scope. All classes in this module inherit from Zeep's Plugin (`zeep.Plugin`) class. """ @@ -18,8 +19,7 @@ class XMLCapturePlugin(Plugin): """ - - + Zeep plugin to capture and inspect SOAP XML requests and responses. @@ -83,7 +83,8 @@ class XMLCapturePlugin(Plugin): """ def __init__(self, pretty_print=True): - """Initialize XML capture plugin. + """ + Initialize XML capture plugin. Args: pretty_print (bool): If True, format XML with indentation @@ -96,7 +97,8 @@ def __init__(self, pretty_print=True): logger.debug("XMLCapturePlugin initialized (pretty_print=%s)", pretty_print) def _format_xml(self, element: etree._Element) -> str: - """Format XML element with proper indentation using lxml. + """ + Format XML element with proper indentation using lxml. Args: element: lxml Element to format @@ -134,8 +136,7 @@ def egress( binding_options: dict[str, object], ) -> tuple[Any, dict[str, str]]: """ - - + Capture a SOAP request before it is sent to the device. @@ -190,8 +191,7 @@ def ingress( self, envelope: etree._Element, http_headers: dict[str, str], operation: Any ) -> tuple[Any, dict[str, str]]: """ - - + Capture a SOAP response after it is received from the device. @@ -241,8 +241,7 @@ def ingress( def get_last_request(self) -> str | None: """ - - + Get the last captured request XML. @@ -253,8 +252,7 @@ def get_last_request(self) -> str | None: def get_last_response(self) -> str | None: """ - - + Get the last captured response XML. @@ -265,8 +263,7 @@ def get_last_response(self) -> str | None: def get_history(self) -> list: """ - - + Get all captured requests and responses. @@ -277,8 +274,7 @@ def get_history(self) -> list: def clear_history(self) -> None: """ - - + Clear the capture history. """ @@ -293,8 +289,7 @@ def save_to_file( self, request_file: str | None = None, response_file: str | None = None ) -> None: """ - - + Save captured XML to files. @@ -372,7 +367,8 @@ class ONVIFParser(Plugin): """ def __init__(self, extract_xpaths: dict[str, str]): - """Initialize XML element parser. + """ + Initialize XML element parser. Args: extract_xpaths: Dictionary mapping names to XPath expressions. @@ -397,8 +393,7 @@ def ingress( self, envelope: etree._Element, http_headers: dict[str, str], operation: Any ) -> tuple[Any, dict[str, str]]: """ - - + Process a SOAP response before Zeep deserializes it. @@ -444,8 +439,7 @@ def ingress( def get_extracted_texts(self, name: str, count: int) -> list[str | None]: """ - - + Get extracted element texts by name. @@ -469,9 +463,7 @@ def get_extracted_texts(self, name: str, count: int) -> list[str | None]: class ReferenceParametersPlugin(Plugin): """ - - - + Zeep plugin for injecting WS-Addressing reference parameters. @@ -497,7 +489,7 @@ class ReferenceParametersPlugin(Plugin): ) def __init__(self, reference_parameters: list[etree._Element] | None = None): - """Initialize Reference Parameters injection""" + """Initialize Reference Parameters injection.""" self.reference_parameters = reference_parameters or [] def egress( @@ -508,8 +500,7 @@ def egress( binding_options: dict[str, object], ) -> tuple[Any, dict[str, str]]: """ - - + Inject WS-Addressing reference parameters into a SOAP request. diff --git a/onvif/utils/service.py b/onvif/utils/service.py index 371c10d..1823252 100644 --- a/onvif/utils/service.py +++ b/onvif/utils/service.py @@ -22,7 +22,8 @@ def deprecated(reason: str) -> Callable[[Callable[P, R]], Callable[P, R]]: - """Mark a function as deprecated and emit a warning when it is called. + """ + Mark a function as deprecated and emit a warning when it is called. Args: reason: Explanation of why the function is deprecated and, when @@ -52,7 +53,8 @@ def wrapper(*args: P.args, **kwargs: P.kwargs) -> R: def _is_zeep_object(obj): - """Check if an object is a Zeep-generated object. + """ + Check if an object is a Zeep-generated object. Zeep objects have the _xsd_type attribute which is the XSD type definition. """ @@ -61,8 +63,7 @@ def _is_zeep_object(obj): class ONVIFService: """ - - + Base class for all ONVIF service implementations. @@ -102,8 +103,7 @@ class ONVIFService: def __getattribute__(self, name: str) -> Any: """ - - + Intercept all method calls and wrap ONVIF operations with error handling. diff --git a/onvif/utils/wsdl.py b/onvif/utils/wsdl.py index cfbd9fc..79b9d22 100644 --- a/onvif/utils/wsdl.py +++ b/onvif/utils/wsdl.py @@ -1,4 +1,6 @@ -"""WSDL file manager for ONVIF services with support for built-in and custom WSDL dir.""" +"""WSDL file manager for ONVIF services with support for built-in and custom WSDL +dir. +""" from __future__ import annotations @@ -14,8 +16,7 @@ class ONVIFWSDL: """ - - + WSDL file manager for ONVIF services. @@ -96,8 +97,7 @@ class ONVIFWSDL: @classmethod def set_custom_wsdl_dir(cls, custom_dir: str) -> None: """ - - + Set global custom WSDL directory for all services. @@ -118,8 +118,7 @@ def set_custom_wsdl_dir(cls, custom_dir: str) -> None: @classmethod def get_custom_wsdl_dir(cls) -> str | None: """ - - + Get current global custom WSDL directory. @@ -139,8 +138,7 @@ def get_custom_wsdl_dir(cls) -> str | None: @classmethod def clear_custom_wsdl_dir(cls) -> None: """ - - + Clear custom WSDL directory, revert to built-in WSDLs. @@ -158,7 +156,8 @@ def clear_custom_wsdl_dir(cls) -> None: @classmethod def _get_base_dir(cls, custom_wsdl_dir: str | None = None) -> str | Any: - """Get the base WSDL directory, using custom directory if provided. + """ + Get the base WSDL directory, using custom directory if provided. This method implements the priority chain for WSDL directory resolution. @@ -186,7 +185,8 @@ def _get_base_dir(cls, custom_wsdl_dir: str | None = None) -> str | Any: def _get_wsdl_map( cls, custom_wsdl_dir: str | None = None ) -> dict[str, dict[str, Any]] | None: - """Get WSDL map with proper base directory. + """ + Get WSDL map with proper base directory. Generates a complete mapping of all ONVIF services to their WSDL definitions. The structure differs based on whether custom WSDLs are used. @@ -244,7 +244,8 @@ def _get_wsdl_map( @classmethod def _ensure_wsdl_map_initialized(cls) -> None: - """Ensure WSDL_MAP is initialized with default values. + """ + Ensure WSDL_MAP is initialized with default values. Lazy initialization of the default WSDL map. This is called automatically before accessing WSDL_MAP to ensure it's not None. @@ -255,8 +256,7 @@ def _ensure_wsdl_map_initialized(cls) -> None: @classmethod def get_wsdl_map(cls) -> dict[str, dict[str, Any]]: """ - - + Get the complete WSDL map for all services. """ @@ -272,8 +272,7 @@ def get_definition( cls, service: str, version: str = "ver10", custom_wsdl_dir=None ) -> dict: """ - - + Get WSDL definition for a specific ONVIF service. diff --git a/onvif/utils/zeep.py b/onvif/utils/zeep.py index e3fb2da..82a4292 100644 --- a/onvif/utils/zeep.py +++ b/onvif/utils/zeep.py @@ -140,7 +140,8 @@ class ZeepPatcher: @staticmethod def _parse_text_value(value): - """Parse text value with type conversion. + """ + Parse text value with type conversion. Converts: - "true"/"false" → bool @@ -170,7 +171,8 @@ def _parse_text_value(value): @staticmethod def _parse_element_recursive(element): - """Recursively parse an XML element and its children into a dictionary. + """ + Recursively parse an XML element and its children into a dictionary. Handles: - Elements with attributes only (converted to dict) @@ -220,7 +222,8 @@ def _parse_element_recursive(element): def _patched_parse_xmlelements( self, xmlelements, schema, name=None, context=None ): # pylint: disable=bad-staticmethod-argument,unused-argument - """Patched version of zeep's Any.parse_xmlelements method. + """ + Patched version of zeep's Any.parse_xmlelements method. This method parses `xsd:any` fields into structured dictionaries instead of leaving them as raw XML elements, making them easier to work with. @@ -333,7 +336,8 @@ def _patched_parse_xmlelements( @staticmethod def _zeep_object_to_dict(obj): - """Convert zeep object to dictionary, including manually added attributes. + """ + Convert zeep object to dictionary, including manually added attributes. Args: obj (Any): Zeep object or primitive value @@ -371,8 +375,7 @@ def _zeep_object_to_dict(obj): @staticmethod def flatten_xsd_any_fields(obj, _visited=None) -> Any: """ - - + Post-process zeep objects to flatten `xsd:any` fields (`_value_1`, `_value_2`, etc.) into the main object. @@ -629,8 +632,7 @@ def flatten_xsd_any_fields(obj, _visited=None) -> Any: @classmethod def apply_patch(cls): """ - - + Inject the custom `parse_xmlelements` method into `zeep.xsd.elements.any.Any`. @@ -656,8 +658,7 @@ def apply_patch(cls): @classmethod def remove_patch(cls): """ - - + Restore the original `parse_xmlelements` method. @@ -681,8 +682,7 @@ def remove_patch(cls): @classmethod def is_patched(cls) -> bool: """ - - + Check if the patch is currently applied. From 7d23c77554276d9348e8cc83547a8cf26b03e0e2 Mon Sep 17 00:00:00 2001 From: Kaburagi <135169292+kaburagisec@users.noreply.github.com> Date: Thu, 22 Oct 2026 02:26:57 +0700 Subject: [PATCH 2/5] style: Run docformatter on tests module --- tests/cli/test_cli_interactive_information.py | 4 +- tests/cli/test_cli_interactive_shell.py | 8 +- tests/cli/test_cli_interactive_utils.py | 6 +- tests/services/base_service_test.py | 10 +- tests/services/test_authenticationbehavior.py | 3 +- tests/services/test_authorizationserver.py | 3 +- tests/services/test_pausable_subscription.py | 3 +- tests/test_meta.py | 3 +- tests/test_operator.py | 84 ++++++++----- tests/utilities/test_discovery.py | 18 ++- tests/utilities/test_plugins.py | 117 ++++++++++++------ tests/utilities/test_service.py | 60 ++++++--- 12 files changed, 213 insertions(+), 106 deletions(-) diff --git a/tests/cli/test_cli_interactive_information.py b/tests/cli/test_cli_interactive_information.py index dad42b3..57fce71 100644 --- a/tests/cli/test_cli_interactive_information.py +++ b/tests/cli/test_cli_interactive_information.py @@ -119,7 +119,9 @@ def test_do_info_displays_basic_connection_information(self, capsys): assert "DEVICE INFO" in output def test_do_info_displays_ws_username_token_when_digest_disabled(self, capsys): - """Verify WS-UsernameToken is displayed when digest authentication is disabled.""" + """Verify WS-UsernameToken is displayed when digest authentication is + disabled. + """ commands = create_commands(digest=False) commands.do_info("") diff --git a/tests/cli/test_cli_interactive_shell.py b/tests/cli/test_cli_interactive_shell.py index 0260a7e..3cae354 100644 --- a/tests/cli/test_cli_interactive_shell.py +++ b/tests/cli/test_cli_interactive_shell.py @@ -35,7 +35,8 @@ def create_args(**overrides): def create_client(): - """Create a mock ONVIF client with the responses required by the shell. + """ + Create a mock ONVIF client with the responses required by the shell. Returns: A mock ONVIF client configured with basic device information and @@ -70,7 +71,6 @@ def create_client(): def create_device_data(): """Create device information data as dict.""" - return { "Manufacturer": "Dahua", "Model": "DH-H5D-5F", @@ -164,7 +164,9 @@ def test_prints_intro_with_device_information(self, client, args, device_data): assert shell.intro == "Interactive ONVIF shell" def test_starts_health_check_after_initialization(self, client, args, device_data): - """Verify that the background health-check thread starts after initialization.""" + """Verify that the background health-check thread starts after + initialization. + """ with patch("onvif.cli.interactive.utils.threading.Thread") as thread_cls: health_thread = thread_cls.return_value diff --git a/tests/cli/test_cli_interactive_utils.py b/tests/cli/test_cli_interactive_utils.py index 5ed6c19..30d0c4e 100644 --- a/tests/cli/test_cli_interactive_utils.py +++ b/tests/cli/test_cli_interactive_utils.py @@ -33,7 +33,8 @@ def create_args(**overrides): def create_context(**overrides): - """Create a mocked shell context for utility tests. + """ + Create a mocked shell context for utility tests. Args: **overrides: Optional context values that should override defaults. @@ -73,7 +74,8 @@ def create_context(**overrides): def create_utilities(): - """Create a minimally initialized ``ShellUtilities`` instance. + """ + Create a minimally initialized ``ShellUtilities`` instance. Returns: A shell utility instance with a mocked shell context. diff --git a/tests/services/base_service_test.py b/tests/services/base_service_test.py index 1e46194..41d9559 100644 --- a/tests/services/base_service_test.py +++ b/tests/services/base_service_test.py @@ -282,7 +282,8 @@ def test_method_parameters_match_wsdl(self): assert False, error_msg def test_method_parameters_completeness(self): - """Test that all WSDL top-level parameters are included in method signature. + """ + Test that all WSDL top-level parameters are included in method signature. This ensures that methods don't miss optional parameters from WSDL. For example, if WSDL has [CertificateID, Subject, Attributes], the method must have all three @@ -463,7 +464,9 @@ def test_operator_call_usage( # pylint: disable=too-many-branches,too-many-nest assert not errors, "Operator call errors:\n" + "\n".join(errors) def test_legacy_call_uses_legacy_operation(self): - """Test that legacy_call temporarily registers and invokes a legacy operation.""" + """Test that legacy_call temporarily registers and invokes a legacy + operation. + """ operator = object.__new__(ONVIFOperator) current_operation = Mock() @@ -558,7 +561,8 @@ def test_no_extra_methods(self): # pylint: disable=too-many-branches,too-many-nested-blocks def test_parameter_forwarding_for_all_methods(self): """Test that all method parameters are correctly forwarded to - operator.call().""" + operator.call(). + """ if not self.SERVICE_CLASS: return diff --git a/tests/services/test_authenticationbehavior.py b/tests/services/test_authenticationbehavior.py index 9644489..b1ad896 100644 --- a/tests/services/test_authenticationbehavior.py +++ b/tests/services/test_authenticationbehavior.py @@ -7,7 +7,8 @@ class TestAuthenticationBehaviorWSDLCompliance(ONVIFServiceTestBase): """Test that AuthenticationBehavior service implementation matches WSDL - specification.""" + specification. + """ # Service-specific configuration SERVICE_CLASS = AuthenticationBehavior diff --git a/tests/services/test_authorizationserver.py b/tests/services/test_authorizationserver.py index 5f0c818..c70853e 100644 --- a/tests/services/test_authorizationserver.py +++ b/tests/services/test_authorizationserver.py @@ -7,7 +7,8 @@ class TestAuthorizationServerWSDLCompliance(ONVIFServiceTestBase): """Test that AuthorizationServer service implementation matches WSDL - specification.""" + specification. + """ # Service-specific configuration SERVICE_CLASS = AuthorizationServer diff --git a/tests/services/test_pausable_subscription.py b/tests/services/test_pausable_subscription.py index 17399d8..ef8e06e 100644 --- a/tests/services/test_pausable_subscription.py +++ b/tests/services/test_pausable_subscription.py @@ -7,7 +7,8 @@ class TestPausableSubscriptionWSDLCompliance(ONVIFServiceTestBase): """Test that PausableSubscription service implementation matches WSDL - specification.""" + specification. + """ # Service-specific configuration SERVICE_CLASS = PausableSubscription diff --git a/tests/test_meta.py b/tests/test_meta.py index ebaacec..915f1e1 100644 --- a/tests/test_meta.py +++ b/tests/test_meta.py @@ -19,7 +19,8 @@ def test_repository(): def test_metadata_annotations(): """Test that the __version__ and __repository__ attributes have the correct type - annotations.""" + annotations. + """ annotations = get_type_hints(meta) assert annotations["__version__"] is Final[str] diff --git a/tests/test_operator.py b/tests/test_operator.py index 372d35a..f43a715 100644 --- a/tests/test_operator.py +++ b/tests/test_operator.py @@ -190,7 +190,8 @@ def test_init_uses_explicit_xaddr(self): def test_init_defaults_service_path_when_empty(self): """Test that ONVIFOperator defaults to the standard service path when - service_path is None.""" + service_path is None. + """ mock_client = Mock() with ( @@ -220,7 +221,8 @@ def test_init_defaults_service_path_when_empty(self): def test_init_creates_default_db_cache_path(self): """Test that ONVIFOperator creates the default database cache path when - CacheMode.DB is used.""" + CacheMode.DB is used. + """ mock_client = Mock() with ( @@ -302,7 +304,8 @@ def test_init_raises_without_binding(self): def test_init_passes_configuration_to_client(self): """Test that ONVIFOperator passes the correct configuration to the Zeep - client.""" + client. + """ mock_client = Mock() mock_wsse = Mock() mock_transport = Mock() @@ -370,7 +373,8 @@ class TestCreateSession: def test_create_session_sets_verify(self): """Test that ONVIFOperator creates a requests.Session with the correct SSL - verification setting.""" + verification setting. + """ operator = make_operator() with patch("onvif.operator.requests.Session") as mock_session_cls: @@ -381,7 +385,8 @@ def test_create_session_sets_verify(self): def test_create_session_disables_ssl_verification(self): """Test that ONVIFOperator creates a requests.Session with SSL verification - disabled.""" + disabled. + """ operator = make_operator() with (patch("onvif.operator.warnings.simplefilter") as mock_filter,): @@ -398,7 +403,8 @@ def test_create_session_disables_ssl_verification(self): def test_create_session_configures_digest_auth(self): """Test that ONVIFOperator creates a requests.Session with HTTP Digest - authentication when enabled.""" + authentication when enabled. + """ operator = make_operator( username="admin", password="secret", @@ -430,7 +436,8 @@ def test_create_session_without_digest_auth( password, ): """Test that ONVIFOperator creates a requests.Session without HTTP Digest - authentication when not enabled or credentials are missing.""" + authentication when not enabled or credentials are missing. + """ operator = make_operator( http_digest=http_digest, username=username, @@ -449,7 +456,8 @@ class TestCreateWsse: def test_create_wsse_returns_none_for_http_digest(self): """Test that ONVIFOperator._create_wsse returns None when HTTP Digest - authentication is enabled.""" + authentication is enabled. + """ operator = make_operator( http_digest=True, username="admin", @@ -476,7 +484,8 @@ def test_create_wsse_returns_none_without_credentials( password, ): """Test that ONVIFOperator._create_wsse returns None when username or password - is missing.""" + is missing. + """ operator = make_operator( http_digest=False, username=username, @@ -491,7 +500,8 @@ def test_create_wsse_returns_none_without_credentials( def test_create_wsse_creates_username_token(self): """Test that ONVIFOperator._create_wsse creates a UsernameToken when HTTP Digest - is disabled and credentials are provided.""" + is disabled and credentials are provided. + """ operator = make_operator( http_digest=False, username="admin", @@ -514,7 +524,8 @@ class TestCall: def test_call_returns_service_result_and_flattens_result(self): """Test that ONVIFOperator.call returns the result from the service and flattens - it using ZeepPatcher.""" + it using ZeepPatcher. + """ service = Mock() service.GetDeviceInformation.return_value = {"raw": "value"} @@ -546,7 +557,8 @@ def test_call_returns_service_result_and_flattens_result(self): def test_call_skips_flatten_when_patch_disabled(self): """Test that ONVIFOperator.call skips flattening the result when apply_patch is - False.""" + False. + """ service = Mock() service.GetDeviceInformation.return_value = "result" @@ -565,7 +577,8 @@ def test_call_skips_flatten_when_patch_disabled(self): def test_call_wraps_missing_method(self): """Test that ONVIFOperator.call raises ONVIFOperationException when the service - method is missing.""" + method is missing. + """ service = Mock(spec=[]) operator = make_operator( @@ -581,7 +594,8 @@ def test_call_wraps_missing_method(self): def test_call_wraps_zeep_fault(self): """Test that ONVIFOperator.call raises ONVIFOperationException when the service - method raises a Zeep Fault.""" + method raises a Zeep Fault. + """ service = Mock() fault = Fault("SOAP fault") service.GetDeviceInformation.side_effect = fault @@ -598,7 +612,8 @@ def test_call_wraps_zeep_fault(self): def test_call_wraps_generic_exception(self): """Test that ONVIFOperator.call raises ONVIFOperationException when the service - method raises a generic exception.""" + method raises a generic exception. + """ service = Mock() error = RuntimeError("connection failed") service.GetDeviceInformation.side_effect = error @@ -615,7 +630,8 @@ def test_call_wraps_generic_exception(self): def test_call_passes_positional_and_keyword_arguments(self): """Test that ONVIFOperator.call correctly passes positional and keyword - arguments to the service method.""" + arguments to the service method. + """ service = Mock() service.GetProfiles.return_value = "result" @@ -642,7 +658,8 @@ class TestCreateType: def test_create_type_succeeds_with_first_namespace(self): """Test that ONVIFOperator.create_type successfully creates a type using the - first namespace when available.""" + first namespace when available. + """ operator = make_operator() element = Mock() instance = Mock() @@ -666,7 +683,8 @@ def test_create_type_succeeds_with_first_namespace(self): def test_create_type_tries_next_namespace_after_failure(self): """Test that ONVIFOperator.create_type tries the next namespace if the first one - fails.""" + fails. + """ operator = make_operator() element = Mock() instance = Mock() @@ -697,7 +715,8 @@ def get_element(name): def test_create_type_falls_back_to_unqualified_element(self): """Test that ONVIFOperator.create_type falls back to an unqualified element if - namespaced elements are not found.""" + namespaced elements are not found. + """ operator = make_operator() element = Mock() instance = Mock() @@ -724,7 +743,8 @@ def get_element(name): def test_create_type_falls_back_to_namespaced_complex_type(self): """Test that ONVIFOperator.create_type falls back to a namespaced complex type - if elements are not found.""" + if elements are not found. + """ operator = make_operator() type_obj = Mock() instance = Mock() @@ -755,7 +775,8 @@ def get_type(name): def test_create_type_falls_back_to_second_complex_type_namespace(self): """Test that ONVIFOperator.create_type falls back to the second complex type - namespace if the first one fails.""" + namespace if the first one fails. + """ operator = make_operator() type_obj = Mock() instance = Mock() @@ -788,7 +809,8 @@ def get_type(name): def test_create_type_falls_back_to_unqualified_complex_type(self): """Test that ONVIFOperator.create_type falls back to an unqualified complex type - if namespaced types are not found.""" + if namespaced types are not found. + """ operator = make_operator() type_obj = Mock() instance = Mock() @@ -815,7 +837,8 @@ def test_create_type_falls_back_to_unqualified_complex_type(self): def test_create_type_raises_when_all_lookup_methods_fail(self): """Test that ONVIFOperator.create_type raises AttributeError when all lookup - methods fail.""" + methods fail. + """ operator = make_operator() operator.client = Mock() operator.client.get_element.side_effect = AttributeError @@ -834,7 +857,8 @@ class TestInitializeNestedTypes: def test_initialize_nested_types_returns_instance_without_xsd_type(self): """Test that _initialize_nested_types returns the instance unchanged when it has - no _xsd_type attribute.""" + no _xsd_type attribute. + """ operator = make_operator() instance = object() @@ -844,7 +868,8 @@ def test_initialize_nested_types_returns_instance_without_xsd_type(self): def test_initialize_nested_types_does_not_replace_existing_value(self): """Test that _initialize_nested_types does not replace an existing value of a - nested type attribute.""" + nested type attribute. + """ operator = make_operator() existing = object() @@ -884,7 +909,8 @@ def __init__(self): def test_initialize_nested_types_ignores_simple_type(self): """Test that _initialize_nested_types does not replace a nested type attribute - if it is a simple type.""" + if it is a simple type. + """ operator = make_operator() class SimpleType: @@ -922,12 +948,14 @@ def __init__(self): def test_initialize_nested_types_handles_xsd_processing_error(self): """Test that _initialize_nested_types handles an AttributeError when accessing - elements of the XSD type.""" + elements of the XSD type. + """ operator = make_operator() class BrokenXsd: """Simulate an XSD type that raises an AttributeError when accessing - elements.""" + elements. + """ @property def elements(self): diff --git a/tests/utilities/test_discovery.py b/tests/utilities/test_discovery.py index 5b28abc..6a6f5f9 100644 --- a/tests/utilities/test_discovery.py +++ b/tests/utilities/test_discovery.py @@ -136,7 +136,8 @@ def test_get_local_ip_hostname_loopback_falls_back_to_empty_string(self, discove def test_get_local_ip_hostname_lookup_failure_returns_empty_string(self, discovery): """Test that get_local_ip returns an empty string when hostname resolution - fails.""" + fails. + """ sock = Mock() sock.connect.side_effect = OSError("network unavailable") @@ -366,7 +367,8 @@ def test_parse_single_response_valid(self, discovery): def test_parse_single_response_without_probe_match_returns_none(self, discovery): """Test that _parse_single_response returns None without a ProbeMatch - element.""" + element. + """ xml = """ @@ -387,7 +389,8 @@ def test_parse_single_response_without_xaddr_returns_default_device_info( discovery, ): """Test that a ProbeMatch without XAddrs returns default connection - information.""" + information. + """ xml = """ TopicA TopicB - """ + + """ ) headers = {"Content-Type": "text/xml"} operation = Mock() @@ -65,7 +68,8 @@ def test_ingress_extracts_multiple_xpath_groups(self): def test_ingress_ignores_xpath_without_matches(self): """Test that the ONVIFParser ignores XPath expressions that do not match any - elements.""" + elements. + """ parser = ONVIFParser( { "topic": ".//{urn:test}Topic", @@ -82,7 +86,8 @@ def test_ingress_ignores_xpath_without_matches(self): def test_ingress_clears_previous_extracted_elements(self): """Test that the ONVIFParser clears previously extracted elements when - processing a new envelope.""" + processing a new envelope. + """ parser = ONVIFParser({"topic": ".//{urn:test}Topic"}) first_envelope = etree.fromstring( @@ -101,7 +106,8 @@ def test_ingress_clears_previous_extracted_elements(self): def test_ingress_handles_elements_without_text(self): """Test that the ONVIFParser handles elements that do not contain text - content.""" + content. + """ parser = ONVIFParser({"topic": ".//{urn:test}Topic"}) envelope = etree.fromstring( """ """ @@ -121,11 +127,13 @@ def test_ingress_raises_for_invalid_xpath(self): def test_get_extracted_texts_returns_available_values(self): """Test that the ONVIFParser returns the extracted text values for a given - name.""" + name. + """ parser = ONVIFParser({"topic": ".//{urn:test}Topic"}) envelope = etree.fromstring( """ TopicA TopicB - """ + + """ ) parser.ingress(envelope, {}, Mock()) @@ -137,11 +145,13 @@ def test_get_extracted_texts_returns_available_values(self): def test_get_extracted_texts_limits_result_to_count(self): """Test that the ONVIFParser limits the number of returned extracted text values - to the specified count.""" + to the specified count. + """ parser = ONVIFParser({"topic": ".//{urn:test}Topic"}) envelope = etree.fromstring( """ TopicA TopicB - TopicC """ + TopicC + """ ) parser.ingress(envelope, {}, Mock()) @@ -153,7 +163,8 @@ def test_get_extracted_texts_limits_result_to_count(self): def test_get_extracted_texts_pads_missing_values_with_none(self): """Test that the ONVIFParser pads the returned list with None for missing values - when the count exceeds the number of extracted elements.""" + when the count exceeds the number of extracted elements. + """ parser = ONVIFParser({"topic": ".//{urn:test}Topic"}) envelope = etree.fromstring( """ TopicA """ @@ -169,7 +180,8 @@ def test_get_extracted_texts_pads_missing_values_with_none(self): def test_get_extracted_texts_returns_empty_list_for_unknown_name(self): """Test that the ONVIFParser returns a list of None values for an unknown - name.""" + name. + """ parser = ONVIFParser({}) assert parser.get_extracted_texts("missing", 3) == [ @@ -190,7 +202,8 @@ class TestXMLCapturePlugin: def test_init_uses_pretty_print_by_default(self): """Test that the XMLCapturePlugin initializes with pretty_print enabled by - default and other attributes set to None or empty.""" + default and other attributes set to None or empty. + """ plugin = XMLCapturePlugin() assert plugin.pretty_print is True @@ -201,14 +214,16 @@ def test_init_uses_pretty_print_by_default(self): def test_init_can_disable_pretty_print(self): """Test that the XMLCapturePlugin can be initialized with pretty_print - disabled.""" + disabled. + """ plugin = XMLCapturePlugin(pretty_print=False) assert plugin.pretty_print is False def test_format_xml_pretty_prints_element(self): """Test that the XMLCapturePlugin formats an XML element with pretty - printing.""" + printing. + """ plugin = XMLCapturePlugin() element = etree.fromstring( "test" @@ -226,7 +241,8 @@ def test_format_xml_returns_fallback_when_formatting_fails( monkeypatch, ): """Test that the XMLCapturePlugin returns a fallback string when formatting - fails.""" + fails. + """ plugin = XMLCapturePlugin() element = etree.fromstring("") @@ -245,7 +261,8 @@ def raise_error(*args, **kwargs): def test_egress_captures_pretty_printed_request(self): """Test that the XMLCapturePlugin captures a SOAP request with pretty - printing.""" + printing. + """ plugin = XMLCapturePlugin() envelope = etree.fromstring( "test" @@ -268,7 +285,8 @@ def test_egress_captures_pretty_printed_request(self): def test_egress_captures_request_without_pretty_print(self): """Test that the XMLCapturePlugin captures a SOAP request without pretty - printing.""" + printing. + """ plugin = XMLCapturePlugin(pretty_print=False) envelope = etree.fromstring( "test" @@ -309,7 +327,8 @@ def test_egress_adds_request_to_history(self): def test_egress_copies_http_headers(self): """Test that the XMLCapturePlugin copies the HTTP headers when capturing a SOAP - request.""" + request. + """ plugin = XMLCapturePlugin() envelope = etree.fromstring("") headers = {"Content-Type": "text/xml"} @@ -324,7 +343,8 @@ def test_egress_copies_http_headers(self): def test_egress_handles_empty_http_headers(self): """Test that the XMLCapturePlugin handles empty HTTP headers when capturing a - SOAP request.""" + SOAP request. + """ plugin = XMLCapturePlugin() envelope = etree.fromstring("") operation = Mock() @@ -336,7 +356,8 @@ def test_egress_handles_empty_http_headers(self): def test_ingress_captures_pretty_printed_response(self): """Test that the XMLCapturePlugin captures a SOAP response with pretty - printing.""" + printing. + """ plugin = XMLCapturePlugin() envelope = etree.fromstring( "response" @@ -353,7 +374,8 @@ def test_ingress_captures_pretty_printed_response(self): def test_ingress_captures_response_without_pretty_print(self): """Test that the XMLCapturePlugin captures a SOAP response without pretty - printing.""" + printing. + """ plugin = XMLCapturePlugin(pretty_print=False) envelope = etree.fromstring( "response" @@ -401,7 +423,8 @@ def test_get_last_request_returns_captured_request(self): def test_get_last_request_returns_none_initially(self): """Test that the XMLCapturePlugin returns None for the last request when no - request has been captured.""" + request has been captured. + """ plugin = XMLCapturePlugin() assert plugin.get_last_request() is None @@ -419,7 +442,8 @@ def test_get_last_response_returns_captured_response(self): def test_get_last_response_returns_none_initially(self): """Test that the XMLCapturePlugin returns None for the last response when no - response has been captured.""" + response has been captured. + """ plugin = XMLCapturePlugin() assert plugin.get_last_response() is None @@ -437,7 +461,8 @@ def test_get_history_returns_capture_history(self): def test_clear_history_resets_all_state(self): """Test that the XMLCapturePlugin clears the capture history and resets all - state.""" + state. + """ plugin = XMLCapturePlugin() envelope = etree.fromstring("") operation = Mock() @@ -460,7 +485,8 @@ def test_clear_history_resets_all_state(self): def test_save_to_file_writes_request_xml(self, tmp_path): """Test that the XMLCapturePlugin saves the last captured SOAP request to a - file.""" + file. + """ plugin = XMLCapturePlugin() envelope = etree.fromstring("") operation = Mock() @@ -476,7 +502,8 @@ def test_save_to_file_writes_request_xml(self, tmp_path): def test_save_to_file_writes_response_xml(self, tmp_path): """Test that the XMLCapturePlugin saves the last captured SOAP response to a - file.""" + file. + """ plugin = XMLCapturePlugin() envelope = etree.fromstring("") operation = Mock() @@ -496,7 +523,8 @@ def test_save_to_file_writes_response_xml(self, tmp_path): def test_save_to_file_writes_both_request_and_response(self, tmp_path): """Test that the XMLCapturePlugin saves both the last captured SOAP request and - response to files.""" + response to files. + """ plugin = XMLCapturePlugin() envelope = etree.fromstring("test") operation = Mock() @@ -521,7 +549,8 @@ def test_save_to_file_does_nothing_without_captured_data( tmp_path, ): """Test that the XMLCapturePlugin does not create files when there is no - captured request or response.""" + captured request or response. + """ plugin = XMLCapturePlugin() request_file = tmp_path / "request.xml" @@ -541,14 +570,16 @@ class TestReferenceParametersPlugin: def test_init_uses_empty_reference_parameters_by_default(self): """Test that the ReferenceParametersPlugin initializes with an empty list of - reference parameters by default.""" + reference parameters by default. + """ plugin = ReferenceParametersPlugin() assert plugin.reference_parameters == [] def test_init_stores_reference_parameters(self): """Test that the ReferenceParametersPlugin initializes with the provided - reference parameters.""" + reference parameters. + """ parameter = etree.Element("{urn:test}Parameter") plugin = ReferenceParametersPlugin([parameter]) @@ -556,7 +587,8 @@ def test_init_stores_reference_parameters(self): def test_egress_rejects_unsupported_soap_namespace(self): """Test that the ReferenceParametersPlugin raises a RuntimeError when the SOAP - envelope namespace is unsupported.""" + envelope namespace is unsupported. + """ plugin = ReferenceParametersPlugin() envelope = etree.Element("{urn:unsupported}Envelope") @@ -575,7 +607,8 @@ def test_egress_rejects_unsupported_soap_namespace(self): ) def test_egress_supports_soap_namespaces(self, soap_namespace): """Test that the ReferenceParametersPlugin supports both SOAP 1.1 and SOAP 1.2 - namespaces.""" + namespaces. + """ plugin = ReferenceParametersPlugin() envelope = etree.Element(f"{{{soap_namespace}}}Envelope") @@ -589,7 +622,8 @@ def test_egress_supports_soap_namespaces(self, soap_namespace): def test_egress_creates_header_when_missing(self): """Test that the ReferenceParametersPlugin creates a SOAP Header element when it - is missing from the envelope.""" + is missing from the envelope. + """ plugin = ReferenceParametersPlugin() envelope = etree.Element(f"{{{plugin.SOAP_NAMESPACES[0]}}}Envelope") @@ -602,7 +636,8 @@ def test_egress_creates_header_when_missing(self): def test_egress_preserves_existing_header(self): """Test that the ReferenceParametersPlugin preserves an existing SOAP Header - element.""" + element. + """ plugin = ReferenceParametersPlugin() namespace = plugin.SOAP_NAMESPACES[0] @@ -624,7 +659,8 @@ def test_egress_preserves_existing_header(self): def test_egress_injects_reference_parameters(self): """Test that the ReferenceParametersPlugin injects the provided reference - parameters into the SOAP Header.""" + parameters into the SOAP Header. + """ namespace = "urn:test" parameter = etree.Element(f"{{{namespace}}}Reference") parameter.text = "value" @@ -643,7 +679,8 @@ def test_egress_injects_reference_parameters(self): def test_egress_deep_copies_reference_parameters(self): """Test that the ReferenceParametersPlugin deep copies the reference parameters - when injecting them into the SOAP Header.""" + when injecting them into the SOAP Header. + """ namespace = "urn:test" parameter = etree.Element(f"{{{namespace}}}Reference") parameter.text = "original" @@ -664,7 +701,8 @@ def test_egress_deep_copies_reference_parameters(self): def test_egress_does_not_modify_reference_parameters(self): """Test that the ReferenceParametersPlugin does not modify the original - reference parameters when injecting them into the SOAP Header.""" + reference parameters when injecting them into the SOAP Header. + """ parameter = etree.Element("{urn:test}Reference") parameter.set("id", "123") parameter.text = "value" @@ -680,7 +718,8 @@ def test_egress_does_not_modify_reference_parameters(self): def test_egress_preserves_http_headers(self): """Test that the ReferenceParametersPlugin preserves the original HTTP headers - when processing a SOAP request.""" + when processing a SOAP request. + """ plugin = ReferenceParametersPlugin() envelope = etree.Element(f"{{{plugin.SOAP_NAMESPACES[0]}}}Envelope") headers = {"Content-Type": "text/xml"} diff --git a/tests/utilities/test_service.py b/tests/utilities/test_service.py index 052abf2..429237f 100644 --- a/tests/utilities/test_service.py +++ b/tests/utilities/test_service.py @@ -141,7 +141,8 @@ def test_getattribute_preserves_method_arguments(self, service): def test_uppercase_method_exception_is_wrapped(self, service): """Test that exceptions raised by uppercase methods are wrapped in - ONVIFOperationException.""" + ONVIFOperationException. + """ def failing_method(): raise ValueError("boom") @@ -156,7 +157,8 @@ def failing_method(): def test_uppercase_method_preserves_onvif_operation_exception(self, service): """Test that ONVIFOperationException raised by uppercase methods is - preserved.""" + preserved. + """ error = ONVIFOperationException( "GetDeviceInformation", RuntimeError("already wrapped"), @@ -174,7 +176,8 @@ def failing_method(): def test_uppercase_method_uses_unknown_service_name_when_missing(self): """Test that ONVIFOperationException uses "Unknown" service name when operator - has no name.""" + has no name. + """ service = object.__new__(TestService) service.operator = Mock(spec=[]) @@ -286,7 +289,8 @@ def test_zeep_object_without_elements_is_passed_normally(self, service): def test_zeep_object_attribute_error_is_wrapped(self, service): """Test that AttributeError raised during Zeep object conversion is wrapped in - ONVIFOperationException.""" + ONVIFOperationException. + """ class Params: """Mock Zeep object with _xsd_type.elements that raises AttributeError.""" @@ -296,7 +300,8 @@ class Params: @property def Missing(self): """Mock property that raises AttributeError to simulate missing - attribute.""" + attribute. + """ raise AttributeError("missing") params = Params() @@ -333,7 +338,8 @@ def test_type_returns_created_type(self, service): def test_type_wraps_exception(self, service): """Test that exceptions raised by operator.create_type are wrapped in - ONVIFOperationException.""" + ONVIFOperationException. + """ service.operator.create_type.side_effect = RuntimeError("creation failed") with pytest.raises(ONVIFOperationException) as exc_info: @@ -346,7 +352,8 @@ def test_type_wraps_exception(self, service): def test_type_wraps_exception_with_operation_name(self, service): """Test that ONVIFOperationException raised by operator.create_type includes - operation name.""" + operation name. + """ service.operator.create_type.side_effect = ValueError("invalid type") with pytest.raises(ONVIFOperationException) as exc_info: @@ -377,7 +384,8 @@ def test_operations_returns_sorted_methods(self, service): def test_operations_excludes_internal_methods(self, service): """Test that operations() excludes internal methods like private methods and - attributes.""" + attributes. + """ operations = service.operations() assert "regular_method" not in operations @@ -388,7 +396,8 @@ def test_operations_excludes_internal_methods(self, service): def test_operations_handles_exception(self, service): """Test that operations() handles exceptions raised by dir() and returns an - empty list.""" + empty list. + """ with patch( "onvif.utils.service.dir", side_effect=RuntimeError("failed"), @@ -399,7 +408,8 @@ def test_operations_handles_exception(self, service): def test_operations_handles_operator_without_service_name(self): """Test that operations() works even when the operator has no service_name - attribute.""" + attribute. + """ service = object.__new__(TestService) service.operator = Mock(spec=[]) @@ -416,7 +426,8 @@ class TestDesc: def test_desc_returns_method_metadata(self, service): """Test that desc() returns method metadata including documentation, required - and optional parameters.""" + and optional parameters. + """ with patch( "onvif.utils.service.get_method_documentation", return_value={"doc": "Get device information."}, @@ -436,7 +447,8 @@ def test_desc_extracts_required_and_optional_parameters( description_service, ): """Test that desc() correctly extracts required and optional parameters from - method signature.""" + method signature. + """ with patch( "onvif.utils.service.get_method_documentation", return_value={"doc": "Get profiles."}, @@ -462,7 +474,8 @@ def test_desc_excludes_self_from_parameters(self, service): def test_desc_returns_none_for_default_documentation(self, service): """Test that desc() returns None for doc when the documentation is a default - placeholder.""" + placeholder. + """ with patch( "onvif.utils.service.get_method_documentation", return_value={ @@ -482,7 +495,8 @@ def test_desc_returns_none_for_default_documentation(self, service): ) def test_desc_filters_default_documentation(self, service, doc): """Test that desc() filters out default documentation and returns None for - doc.""" + doc. + """ with patch( "onvif.utils.service.get_method_documentation", return_value={"doc": doc}, @@ -493,7 +507,8 @@ def test_desc_filters_default_documentation(self, service, doc): def test_desc_accepts_missing_documentation(self, service): """Test that desc() handles missing documentation gracefully and returns None - for doc.""" + for doc. + """ with patch( "onvif.utils.service.get_method_documentation", return_value=None, @@ -516,7 +531,8 @@ def test_desc_documentation_failure_is_non_fatal( exception, ): """Test that desc() handles documentation retrieval failures gracefully and - returns None for doc.""" + returns None for doc. + """ with patch( "onvif.utils.service.get_method_documentation", side_effect=exception, @@ -528,7 +544,8 @@ def test_desc_documentation_failure_is_non_fatal( def test_desc_parameter_inspection_failure_is_non_fatal(self, service): """Test that desc() handles parameter inspection failures gracefully and returns - empty required/optional lists.""" + empty required/optional lists. + """ with ( patch( "onvif.utils.service.inspect.signature", @@ -555,7 +572,8 @@ def test_desc_unknown_method_raises_onvif_operation_exception(self, service): def test_desc_unknown_method_includes_available_methods(self, service): """Test that desc() includes available methods in the exception message for - unknown methods.""" + unknown methods. + """ with pytest.raises(ONVIFOperationException) as exc_info: service.desc("DoesNotExist") @@ -567,7 +585,8 @@ def test_desc_unknown_method_includes_available_methods(self, service): def test_desc_truncates_long_available_method_list(self): """Test that desc() truncates long available method lists in the exception - message.""" + message. + """ class ManyMethods(ONVIFService): """Concrete test implementation of ONVIFService with many methods.""" @@ -613,7 +632,8 @@ def Golf(self): def test_desc_uses_unknown_service_name_when_operator_has_no_name(self): """Test that desc() uses "Unknown" service name when operator has no - service_name attribute.""" + service_name attribute. + """ service = object.__new__(TestService) service.operator = Mock(spec=[]) From 9dbd659ee1d07b7c232da369ca9cfabd5abf7b04 Mon Sep 17 00:00:00 2001 From: Kaburagi <135169292+kaburagisec@users.noreply.github.com> Date: Thu, 22 Oct 2026 02:27:45 +0700 Subject: [PATCH 3/5] style: Run docformatter on docs folder --- docs/hooks/shortcodes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/hooks/shortcodes.py b/docs/hooks/shortcodes.py index 5c4ade8..880f7e7 100644 --- a/docs/hooks/shortcodes.py +++ b/docs/hooks/shortcodes.py @@ -1,4 +1,5 @@ -"""Shortcodes hook. +""" +Shortcodes hook. Origin source: https://github.com/squidfunk/mkdocs-material/blob/master/src/overrides/hooks/shortcodes.py @@ -112,7 +113,6 @@ def on_page_markdown( def replace(match: Match, page: Page | None = None, files: Files | None = None): """Shortcodes replacer.""" - type, args = match.groups() args = args.strip() From ca215b2d7032802fa3c0fae0f44eca0ae5a0faf1 Mon Sep 17 00:00:00 2001 From: Kaburagi <135169292+kaburagisec@users.noreply.github.com> Date: Thu, 22 Oct 2026 02:28:33 +0700 Subject: [PATCH 4/5] docs: Update contributing guide regarding docformatter --- docs/project/contributing.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/project/contributing.md b/docs/project/contributing.md index d5de8f5..0ad2317 100644 --- a/docs/project/contributing.md +++ b/docs/project/contributing.md @@ -102,8 +102,9 @@ isort . # Spelling check codespell . -# Format docstring with docformatter -docformatter --recursive --black --in-place . +# Format docstring with docformatter +# (for onvif, tests, and docs folders only) +docformatter --recursive --black --in-place onvif tests docs # Format code with black black . @@ -216,13 +217,16 @@ The documentation source is located in the [`docs/`](https://github.com/nirsimet ```text docs/ ├── assets/ +├── generated/ ├── hooks/ ├── javascripts/ ├── stylesheets/ ├── overrides/ +├── templates/ ├── includes/ ├── api/ ├── main/ +├── misc/ ├── references/ ├── utilities/ ├── project/ From 1edf8257821c577949f583f6e8741ecb8f0586f9 Mon Sep 17 00:00:00 2001 From: Kaburagi <135169292+kaburagisec@users.noreply.github.com> Date: Thu, 22 Oct 2026 03:01:10 +0700 Subject: [PATCH 5/5] style: Suppress pylint too-many-lines on devicemgmt --- onvif/services/devicemgmt.py | 1 + 1 file changed, 1 insertion(+) diff --git a/onvif/services/devicemgmt.py b/onvif/services/devicemgmt.py index 1217edb..064f439 100644 --- a/onvif/services/devicemgmt.py +++ b/onvif/services/devicemgmt.py @@ -1,3 +1,4 @@ +# pylint: disable=too-many-lines """Device (Core) service implementation.""" from onvif.operator import ONVIFOperator