onvif-python 0.2.11__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. {onvif_python-0.2.11/onvif_python.egg-info → onvif_python-0.3.0}/PKG-INFO +23 -23
  2. {onvif_python-0.2.11 → onvif_python-0.3.0}/README.md +21 -21
  3. onvif_python-0.3.0/onvif/__init__.py +25 -0
  4. onvif_python-0.3.0/onvif/cli/__init__.py +5 -0
  5. onvif_python-0.3.0/onvif/cli/__main__.py +7 -0
  6. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/cli/interactive.py +53 -45
  7. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/cli/main.py +28 -16
  8. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/cli/utils.py +32 -139
  9. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/client.py +116 -94
  10. onvif_python-0.3.0/onvif/meta.py +6 -0
  11. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/operator.py +80 -30
  12. onvif_python-0.3.0/onvif/services/__init__.py +79 -0
  13. onvif_python-0.3.0/onvif/services/accesscontrol.py +290 -0
  14. onvif_python-0.3.0/onvif/services/accessrules.py +126 -0
  15. onvif_python-0.3.0/onvif/services/actionengine.py +107 -0
  16. onvif_python-0.3.0/onvif/services/analytics/analytics.py +122 -0
  17. onvif_python-0.3.0/onvif/services/analytics/ruleengine.py +76 -0
  18. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/services/analyticsdevice.py +57 -23
  19. onvif_python-0.3.0/onvif/services/appmgmt.py +72 -0
  20. onvif_python-0.3.0/onvif/services/authenticationbehavior.py +217 -0
  21. onvif_python-0.3.0/onvif/services/credential.py +319 -0
  22. onvif_python-0.3.0/onvif/services/deviceio.py +322 -0
  23. onvif_python-0.3.0/onvif/services/devicemgmt.py +965 -0
  24. onvif_python-0.3.0/onvif/services/display.py +130 -0
  25. onvif_python-0.3.0/onvif/services/doorcontrol.py +265 -0
  26. onvif_python-0.3.0/onvif/services/events/events.py +85 -0
  27. onvif_python-0.3.0/onvif/services/events/notification.py +72 -0
  28. onvif_python-0.3.0/onvif/services/events/pausable_subscription.py +72 -0
  29. onvif_python-0.3.0/onvif/services/events/pullpoint.py +78 -0
  30. onvif_python-0.3.0/onvif/services/events/subscription.py +52 -0
  31. onvif_python-0.3.0/onvif/services/imaging.py +141 -0
  32. onvif_python-0.3.0/onvif/services/media.py +884 -0
  33. onvif_python-0.3.0/onvif/services/media2.py +664 -0
  34. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/services/provisioning.py +21 -8
  35. onvif_python-0.3.0/onvif/services/ptz.py +378 -0
  36. onvif_python-0.3.0/onvif/services/receiver.py +92 -0
  37. onvif_python-0.3.0/onvif/services/recording.py +287 -0
  38. onvif_python-0.3.0/onvif/services/replay.py +58 -0
  39. onvif_python-0.3.0/onvif/services/schedule.py +180 -0
  40. onvif_python-0.3.0/onvif/services/search.py +401 -0
  41. onvif_python-0.3.0/onvif/services/security/advancedsecurity.py +33 -0
  42. onvif_python-0.3.0/onvif/services/security/authorizationserver.py +51 -0
  43. onvif_python-0.3.0/onvif/services/security/dot1x.py +159 -0
  44. onvif_python-0.3.0/onvif/services/security/jwt.py +35 -0
  45. onvif_python-0.3.0/onvif/services/security/keystore.py +610 -0
  46. onvif_python-0.3.0/onvif/services/security/mediasigning.py +76 -0
  47. onvif_python-0.3.0/onvif/services/security/tlsserver.py +260 -0
  48. onvif_python-0.3.0/onvif/services/thermal.py +86 -0
  49. onvif_python-0.3.0/onvif/services/uplink.py +54 -0
  50. onvif_python-0.3.0/onvif/utils/__init__.py +21 -0
  51. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/utils/discovery.py +1 -0
  52. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/utils/error_handlers.py +22 -16
  53. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/utils/exceptions.py +1 -0
  54. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/utils/service.py +5 -8
  55. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/utils/wsdl.py +4 -3
  56. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/utils/zeep.py +4 -3
  57. {onvif_python-0.2.11 → onvif_python-0.3.0/onvif_python.egg-info}/PKG-INFO +23 -23
  58. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif_python.egg-info/SOURCES.txt +1 -0
  59. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif_python.egg-info/requires.txt +1 -1
  60. {onvif_python-0.2.11 → onvif_python-0.3.0}/pyproject.toml +34 -2
  61. {onvif_python-0.2.11 → onvif_python-0.3.0}/setup.py +2 -0
  62. {onvif_python-0.2.11 → onvif_python-0.3.0}/tests/test_client.py +24 -24
  63. {onvif_python-0.2.11 → onvif_python-0.3.0}/tests/test_core.py +63 -34
  64. {onvif_python-0.2.11 → onvif_python-0.3.0}/tests/test_error_handlers.py +22 -22
  65. {onvif_python-0.2.11 → onvif_python-0.3.0}/tests/test_exceptions.py +21 -21
  66. onvif_python-0.2.11/onvif/__init__.py +0 -33
  67. onvif_python-0.2.11/onvif/cli/__init__.py +0 -5
  68. onvif_python-0.2.11/onvif/cli/__main__.py +0 -7
  69. onvif_python-0.2.11/onvif/services/__init__.py +0 -79
  70. onvif_python-0.2.11/onvif/services/accesscontrol.py +0 -121
  71. onvif_python-0.2.11/onvif/services/accessrules.py +0 -52
  72. onvif_python-0.2.11/onvif/services/actionengine.py +0 -51
  73. onvif_python-0.2.11/onvif/services/analytics/analytics.py +0 -65
  74. onvif_python-0.2.11/onvif/services/analytics/ruleengine.py +0 -49
  75. onvif_python-0.2.11/onvif/services/appmgmt.py +0 -45
  76. onvif_python-0.2.11/onvif/services/authenticationbehavior.py +0 -88
  77. onvif_python-0.2.11/onvif/services/credential.py +0 -164
  78. onvif_python-0.2.11/onvif/services/deviceio.py +0 -170
  79. onvif_python-0.2.11/onvif/services/devicemgmt.py +0 -425
  80. onvif_python-0.2.11/onvif/services/display.py +0 -67
  81. onvif_python-0.2.11/onvif/services/doorcontrol.py +0 -98
  82. onvif_python-0.2.11/onvif/services/events/events.py +0 -46
  83. onvif_python-0.2.11/onvif/services/events/notification.py +0 -38
  84. onvif_python-0.2.11/onvif/services/events/pausable_subscription.py +0 -31
  85. onvif_python-0.2.11/onvif/services/events/pullpoint.py +0 -33
  86. onvif_python-0.2.11/onvif/services/events/subscription.py +0 -25
  87. onvif_python-0.2.11/onvif/services/imaging.py +0 -69
  88. onvif_python-0.2.11/onvif/services/media.py +0 -429
  89. onvif_python-0.2.11/onvif/services/media2.py +0 -340
  90. onvif_python-0.2.11/onvif/services/ptz.py +0 -192
  91. onvif_python-0.2.11/onvif/services/receiver.py +0 -51
  92. onvif_python-0.2.11/onvif/services/recording.py +0 -171
  93. onvif_python-0.2.11/onvif/services/replay.py +0 -35
  94. onvif_python-0.2.11/onvif/services/schedule.py +0 -87
  95. onvif_python-0.2.11/onvif/services/search.py +0 -218
  96. onvif_python-0.2.11/onvif/services/security/advancedsecurity.py +0 -24
  97. onvif_python-0.2.11/onvif/services/security/authorizationserver.py +0 -36
  98. onvif_python-0.2.11/onvif/services/security/dot1x.py +0 -47
  99. onvif_python-0.2.11/onvif/services/security/jwt.py +0 -26
  100. onvif_python-0.2.11/onvif/services/security/keystore.py +0 -213
  101. onvif_python-0.2.11/onvif/services/security/mediasigning.py +0 -35
  102. onvif_python-0.2.11/onvif/services/security/tlsserver.py +0 -87
  103. onvif_python-0.2.11/onvif/services/thermal.py +0 -59
  104. onvif_python-0.2.11/onvif/services/uplink.py +0 -33
  105. onvif_python-0.2.11/onvif/utils/__init__.py +0 -21
  106. {onvif_python-0.2.11 → onvif_python-0.3.0}/LICENSE.md +0 -0
  107. {onvif_python-0.2.11 → onvif_python-0.3.0}/MANIFEST.in +0 -0
  108. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/db/companies.db +0 -0
  109. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/db/products.db +0 -0
  110. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/utils/parser.py +0 -0
  111. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/utils/xml_capture.py +0 -0
  112. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/LICENSE.md +0 -0
  113. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/schema/common/b-2.xsd +0 -0
  114. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/schema/common/bf-2.xsd +0 -0
  115. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/schema/common/bw-2.wsdl +0 -0
  116. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/schema/common/include +0 -0
  117. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/schema/common/mpqf.xsd +0 -0
  118. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/schema/common/r-2.xsd +0 -0
  119. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/schema/common/rw-2.wsdl +0 -0
  120. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/schema/common/soap-envelope +0 -0
  121. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/schema/common/t-1.xsd +0 -0
  122. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/schema/common/ws-addr.xsd +0 -0
  123. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/schema/common/xml.xsd +0 -0
  124. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/schema/common/xmlmime +0 -0
  125. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/accesscontrol/wsdl/index.html +0 -0
  126. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/accessrules/wsdl/accessrules.wsdl +0 -0
  127. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/accessrules/wsdl/index.html +0 -0
  128. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/actionengine.wsdl +0 -0
  129. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/advancedsecurity/wsdl/advancedsecurity.wsdl +0 -0
  130. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/advancedsecurity/wsdl/index.html +0 -0
  131. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/analyticsdevice.wsdl +0 -0
  132. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/appmgmt/wsdl/appmgmt.wsdl +0 -0
  133. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/appmgmt/wsdl/index.html +0 -0
  134. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/authenticationbehavior/wsdl/authenticationbehavior.wsdl +0 -0
  135. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/authenticationbehavior/wsdl/index.html +0 -0
  136. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/credential/wsdl/credential.wsdl +0 -0
  137. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/credential/wsdl/index.html +0 -0
  138. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/device/wsdl/devicemgmt.wsdl +0 -0
  139. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/deviceio.wsdl +0 -0
  140. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/display/display.wsdl +0 -0
  141. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/display/wsdl/index.htm +0 -0
  142. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/display.wsdl +0 -0
  143. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/doorcontrol/wsdl/index.html +0 -0
  144. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/events/wsdl/bw-2-vs-mod.wsdl +0 -0
  145. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/events/wsdl/event-vs.wsdl +0 -0
  146. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/events/wsdl/event.wsdl +0 -0
  147. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/events/wsdl/index.html +0 -0
  148. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/federatedsearch.wsdl +0 -0
  149. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/media/wsdl/media.wsdl +0 -0
  150. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/pacs/accesscontrol.wsdl +0 -0
  151. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/pacs/doorcontrol.wsdl +0 -0
  152. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/pacs/types.xsd +0 -0
  153. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/provisioning/wsdl/provisioning.wsdl +0 -0
  154. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/receiver.wsdl +0 -0
  155. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/recording.wsdl +0 -0
  156. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/replay.wsdl +0 -0
  157. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/schedule/wsdl/index.html +0 -0
  158. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/schedule/wsdl/schedule.wsdl +0 -0
  159. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/schema/common.xsd +0 -0
  160. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/schema/metadatastream.xsd +0 -0
  161. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/schema/onvif.xsd +0 -0
  162. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/search.wsdl +0 -0
  163. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/thermal/wsdl/index.html +0 -0
  164. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/thermal/wsdl/thermal.wsdl +0 -0
  165. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/topics/topicns.xml +0 -0
  166. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/uplink/wsdl/index.html +0 -0
  167. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver10/uplink/wsdl/uplink.wsdl +0 -0
  168. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver20/analytics/humanbody.xsd +0 -0
  169. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver20/analytics/humanface.xsd +0 -0
  170. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver20/analytics/index.html +0 -0
  171. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver20/analytics/radiometry.xsd +0 -0
  172. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver20/analytics/rules.xsd +0 -0
  173. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver20/analytics/wsdl/analytics.wsdl +0 -0
  174. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver20/analytics/wsdl/index.html +0 -0
  175. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver20/imaging/wsdl/imaging.wsdl +0 -0
  176. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver20/media/wsdl/index.html +0 -0
  177. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver20/media/wsdl/media.wsdl +0 -0
  178. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver20/ptz/wsdl/ptz.wsdl +0 -0
  179. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver20/util/federated_search_documentation.html +0 -0
  180. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver20/util/fedsearch-docu-viewer.xsl +0 -0
  181. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver20/util/onvif-wsdl-viewer.xsl +0 -0
  182. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif/wsdl/ver20/util/operationIndex.html +0 -0
  183. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif_python.egg-info/dependency_links.txt +0 -0
  184. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif_python.egg-info/entry_points.txt +0 -0
  185. {onvif_python-0.2.11 → onvif_python-0.3.0}/onvif_python.egg-info/top_level.txt +0 -0
  186. {onvif_python-0.2.11 → onvif_python-0.3.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: onvif-python
3
- Version: 0.2.11
3
+ Version: 0.3.0
4
4
  Summary: A modern Python library for ONVIF-compliant devices
5
5
  Author-email: Nirsimetri Technologies® <open@nirsimetri.com>
6
6
  Maintainer: Kaburagi
@@ -38,10 +38,10 @@ Requires-Dist: requests>=2.32.0
38
38
  Provides-Extra: dev
39
39
  Requires-Dist: pytest>=7.0; extra == "dev"
40
40
  Requires-Dist: black; extra == "dev"
41
- Requires-Dist: flake8; extra == "dev"
42
41
  Requires-Dist: mypy; extra == "dev"
43
42
  Requires-Dist: isort; extra == "dev"
44
43
  Requires-Dist: pylint; extra == "dev"
44
+ Requires-Dist: docformatter; extra == "dev"
45
45
  Dynamic: license-file
46
46
 
47
47
  <h1 align="center">ONVIF Python</h1>
@@ -49,7 +49,7 @@ Dynamic: license-file
49
49
  <div align="center">
50
50
  <a href="https://app.codacy.com/gh/nirsimetri/onvif-python/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade"><img src="https://app.codacy.com/project/badge/Grade/bff08a94e4d447b690cea49c6594826d"/></a>
51
51
  <a href="https://deepwiki.com/nirsimetri/onvif-python"><img alt="Ask DeepWiki" src="https://deepwiki.com/badge.svg"></a>
52
- <a href="https://pypi.org/project/onvif-python/"><img alt="PyPI Version" src="https://img.shields.io/badge/PyPI-0.2.11-orange?logo=archive&color=yellow"></a>
52
+ <a href="https://pypi.org/project/onvif-python/"><img alt="PyPI Version" src="https://img.shields.io/badge/PyPI-0.3.0-orange?logo=archive&color=yellow"></a>
53
53
  <a href="https://pepy.tech/projects/onvif-python"><img alt="Pepy Total Downloads" src="https://img.shields.io/pepy/dt/onvif-python?label=Downloads&color=red"></a>
54
54
  <br>
55
55
  <a href="https://github.com/nirsimetri/onvif-python/actions/workflows/python-app.yml"><img alt="Build" src="https://github.com/nirsimetri/onvif-python/actions/workflows/python-app.yml/badge.svg?branch=main"></a>
@@ -363,13 +363,12 @@ This library includes a powerful command-line interface (CLI) for interacting wi
363
363
  <summary><b>1. Direct CLI</b></summary>
364
364
 
365
365
  ```bash
366
- usage: onvif [-h] [--host HOST] [--port PORT] [--username USERNAME] [--password PASSWORD] [--discover]
367
- [--filter FILTER] [--interface INTERFACE] [--search SEARCH] [--page PAGE] [--per-page PER_PAGE]
368
- [--timeout TIMEOUT] [--https] [--no-verify] [--no-patch] [--interactive] [--debug] [--wsdl WSDL]
369
- [--cache {all,db,mem,none}] [--health-check-interval HEALTH_CHECK_INTERVAL] [--output OUTPUT] [--version]
366
+ usage: onvif [-h] [--host HOST] [--port PORT] [--username USERNAME] [--password PASSWORD] [--discover] [--filter FILTER] [--interface INTERFACE] [--discovery-timeout DISCOVERY_TIMEOUT] [--search SEARCH]
367
+ [--page PAGE] [--per-page PER_PAGE] [--timeout TIMEOUT] [--https] [--no-verify] [--no-patch] [--interactive] [--debug] [--wsdl WSDL] [--cache {all,db,mem,none}]
368
+ [--health-check-interval HEALTH_CHECK_INTERVAL] [--output OUTPUT] [--version]
370
369
  [service] [method] [params ...]
371
370
 
372
- ONVIF Terminal Client — v0.2.11
371
+ ONVIF Terminal Client — v0.3.0
373
372
  https://github.com/nirsimetri/onvif-python
374
373
 
375
374
  positional arguments:
@@ -390,11 +389,13 @@ options:
390
389
  Filter discovered devices by types or scopes (case-insensitive substring match)
391
390
  --interface INTERFACE, -if INTERFACE
392
391
  Specify network interface IP for discovery (default: auto-detect)
392
+ --discovery-timeout DISCOVERY_TIMEOUT, -dt DISCOVERY_TIMEOUT
393
+ Discovery timeout in seconds (default: 4)
393
394
  --search SEARCH, -s SEARCH
394
395
  Search ONVIF products database by model or company (e.g., 'c210', 'hikvision')
395
396
  --page PAGE Page number for search results (default: 1)
396
397
  --per-page PER_PAGE Number of results per page (default: 20)
397
- --timeout TIMEOUT Connection timeout in seconds (default: 10)
398
+ --timeout TIMEOUT ONVIF connection timeout in seconds (default: 10)
398
399
  --https Use HTTPS instead of HTTP
399
400
  --no-verify Disable SSL certificate verification
400
401
  --no-patch Disable ZeepPatcher
@@ -402,13 +403,11 @@ options:
402
403
  --debug Enable debug mode with XML capture
403
404
  --wsdl WSDL Custom WSDL directory path
404
405
  --cache {all,db,mem,none}
405
- Caching mode for ONVIFClient (default: all). 'all': memory+disk, 'db': disk-only, 'mem':
406
- memory-only, 'none': disabled.
406
+ Caching mode for ONVIFClient (default: all). 'all': memory+disk, 'db': disk-only, 'mem': memory-only, 'none': disabled.
407
407
  --health-check-interval HEALTH_CHECK_INTERVAL, -hci HEALTH_CHECK_INTERVAL
408
408
  Health check interval in seconds for interactive mode (default: 10)
409
409
  --output OUTPUT, -o OUTPUT
410
- Save command output to file. Supports .json, .xml extensions for format detection, or plain
411
- text. XML format automatically enables debug mode for SOAP capture.
410
+ Save command output to file. Supports .json, .xml extensions for format detection, or plain text. XML format automatically enables debug mode for SOAP capture.
412
411
  --version, -v Show ONVIF CLI version and exit
413
412
 
414
413
  Examples:
@@ -453,7 +452,7 @@ Examples:
453
452
  <summary><b>2. Interactive Shell</b></summary>
454
453
 
455
454
  ```bash
456
- ONVIF Interactive Shell — v0.2.11
455
+ ONVIF Interactive Shell — v0.3.0
457
456
  https://github.com/nirsimetri/onvif-python
458
457
 
459
458
  Basic Commands:
@@ -548,7 +547,7 @@ If you omit the username or password, you will be prompted to enter them securel
548
547
  | `desc <method>` | Show documentation for a method |
549
548
  | `store <name>` | Store the last result with a variable name |
550
549
  | `show <name>` | Display a stored variable |
551
- | `exit` / `quit` | Exit the shell |
550
+ | `exit` | Exit the shell |
552
551
 
553
552
  > [!IMPORTANT]
554
553
  > You can see all the other commands available in the interactive shell by trying it out directly. The interactive shell runs periodic background health checks to detect connection loss. It uses silent TCP pings to avoid interrupting your work and will automatically exit if the device is unreachable, similar to an SSH session.
@@ -743,8 +742,9 @@ The `ONVIFClient` class provides various configuration options to customize the
743
742
  |-----------|------|----------|---------|-------------|
744
743
  | `host` | `str` | ✅ Yes | - | IP address or hostname of the ONVIF device (e.g., `"192.168.1.17"`) |
745
744
  | `port` | `int` | ✅ Yes | - | Port number for ONVIF service (common ports: `80`, `8000`, `8080`) |
746
- | `username` | `str` | ✅ Yes | - | Username for device authentication (use digest authentication) |
747
- | `password` | `str` | ✅ Yes | - | Password for device authentication |
745
+ | `username` | `str` | ❌ No | - | Username for device authentication |
746
+ | `password` | `str` | ❌ No | - | Password for device authentication |
747
+ | `http_digest` | `str` | ❌ No | `False` | `True` = use HTTP Digest / `False` = use WS-Usernametoken |
748
748
 
749
749
  </details>
750
750
 
@@ -755,7 +755,7 @@ The `ONVIFClient` class provides various configuration options to customize the
755
755
  |-----------|------|----------|---------|-------------|
756
756
  | `timeout` | `int` | ❌ No | `10` | Connection timeout in seconds for SOAP requests |
757
757
  | `use_https` | `bool` | ❌ No | `False` | Use HTTPS instead of HTTP for secure communication |
758
- | `verify_ssl` | `bool` | ❌ No | `True` | Verify SSL certificates when using HTTPS (set to `False` for self-signed certificates) |
758
+ | `verify_ssl` | `bool` | ❌ No | `False` | Verify SSL certificates when using HTTPS (set to `False` for self-signed certificates) |
759
759
 
760
760
  </details>
761
761
 
@@ -1145,11 +1145,11 @@ Some ONVIF services have multiple bindings in the same WSDL. These typically inc
1145
1145
  ```python
1146
1146
  client.security() # root binding
1147
1147
  client.jwt() # sub-binding accessor
1148
- client.authorizationserver(xaddr) # sub-binding accessor (requires xAddr)
1149
- client.keystore(xaddr) # ..
1150
- client.dot1x(xaddr)
1151
- client.tlsserver(xaddr)
1152
- client.mediasigning(xaddr)
1148
+ client.authorizationserver() # ..
1149
+ client.keystore()
1150
+ client.dot1x()
1151
+ client.tlsserver()
1152
+ client.mediasigning()
1153
1153
  ```
1154
1154
 
1155
1155
  3. **Analytics**
@@ -3,7 +3,7 @@
3
3
  <div align="center">
4
4
  <a href="https://app.codacy.com/gh/nirsimetri/onvif-python/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade"><img src="https://app.codacy.com/project/badge/Grade/bff08a94e4d447b690cea49c6594826d"/></a>
5
5
  <a href="https://deepwiki.com/nirsimetri/onvif-python"><img alt="Ask DeepWiki" src="https://deepwiki.com/badge.svg"></a>
6
- <a href="https://pypi.org/project/onvif-python/"><img alt="PyPI Version" src="https://img.shields.io/badge/PyPI-0.2.11-orange?logo=archive&color=yellow"></a>
6
+ <a href="https://pypi.org/project/onvif-python/"><img alt="PyPI Version" src="https://img.shields.io/badge/PyPI-0.3.0-orange?logo=archive&color=yellow"></a>
7
7
  <a href="https://pepy.tech/projects/onvif-python"><img alt="Pepy Total Downloads" src="https://img.shields.io/pepy/dt/onvif-python?label=Downloads&color=red"></a>
8
8
  <br>
9
9
  <a href="https://github.com/nirsimetri/onvif-python/actions/workflows/python-app.yml"><img alt="Build" src="https://github.com/nirsimetri/onvif-python/actions/workflows/python-app.yml/badge.svg?branch=main"></a>
@@ -317,13 +317,12 @@ This library includes a powerful command-line interface (CLI) for interacting wi
317
317
  <summary><b>1. Direct CLI</b></summary>
318
318
 
319
319
  ```bash
320
- usage: onvif [-h] [--host HOST] [--port PORT] [--username USERNAME] [--password PASSWORD] [--discover]
321
- [--filter FILTER] [--interface INTERFACE] [--search SEARCH] [--page PAGE] [--per-page PER_PAGE]
322
- [--timeout TIMEOUT] [--https] [--no-verify] [--no-patch] [--interactive] [--debug] [--wsdl WSDL]
323
- [--cache {all,db,mem,none}] [--health-check-interval HEALTH_CHECK_INTERVAL] [--output OUTPUT] [--version]
320
+ usage: onvif [-h] [--host HOST] [--port PORT] [--username USERNAME] [--password PASSWORD] [--discover] [--filter FILTER] [--interface INTERFACE] [--discovery-timeout DISCOVERY_TIMEOUT] [--search SEARCH]
321
+ [--page PAGE] [--per-page PER_PAGE] [--timeout TIMEOUT] [--https] [--no-verify] [--no-patch] [--interactive] [--debug] [--wsdl WSDL] [--cache {all,db,mem,none}]
322
+ [--health-check-interval HEALTH_CHECK_INTERVAL] [--output OUTPUT] [--version]
324
323
  [service] [method] [params ...]
325
324
 
326
- ONVIF Terminal Client — v0.2.11
325
+ ONVIF Terminal Client — v0.3.0
327
326
  https://github.com/nirsimetri/onvif-python
328
327
 
329
328
  positional arguments:
@@ -344,11 +343,13 @@ options:
344
343
  Filter discovered devices by types or scopes (case-insensitive substring match)
345
344
  --interface INTERFACE, -if INTERFACE
346
345
  Specify network interface IP for discovery (default: auto-detect)
346
+ --discovery-timeout DISCOVERY_TIMEOUT, -dt DISCOVERY_TIMEOUT
347
+ Discovery timeout in seconds (default: 4)
347
348
  --search SEARCH, -s SEARCH
348
349
  Search ONVIF products database by model or company (e.g., 'c210', 'hikvision')
349
350
  --page PAGE Page number for search results (default: 1)
350
351
  --per-page PER_PAGE Number of results per page (default: 20)
351
- --timeout TIMEOUT Connection timeout in seconds (default: 10)
352
+ --timeout TIMEOUT ONVIF connection timeout in seconds (default: 10)
352
353
  --https Use HTTPS instead of HTTP
353
354
  --no-verify Disable SSL certificate verification
354
355
  --no-patch Disable ZeepPatcher
@@ -356,13 +357,11 @@ options:
356
357
  --debug Enable debug mode with XML capture
357
358
  --wsdl WSDL Custom WSDL directory path
358
359
  --cache {all,db,mem,none}
359
- Caching mode for ONVIFClient (default: all). 'all': memory+disk, 'db': disk-only, 'mem':
360
- memory-only, 'none': disabled.
360
+ Caching mode for ONVIFClient (default: all). 'all': memory+disk, 'db': disk-only, 'mem': memory-only, 'none': disabled.
361
361
  --health-check-interval HEALTH_CHECK_INTERVAL, -hci HEALTH_CHECK_INTERVAL
362
362
  Health check interval in seconds for interactive mode (default: 10)
363
363
  --output OUTPUT, -o OUTPUT
364
- Save command output to file. Supports .json, .xml extensions for format detection, or plain
365
- text. XML format automatically enables debug mode for SOAP capture.
364
+ Save command output to file. Supports .json, .xml extensions for format detection, or plain text. XML format automatically enables debug mode for SOAP capture.
366
365
  --version, -v Show ONVIF CLI version and exit
367
366
 
368
367
  Examples:
@@ -407,7 +406,7 @@ Examples:
407
406
  <summary><b>2. Interactive Shell</b></summary>
408
407
 
409
408
  ```bash
410
- ONVIF Interactive Shell — v0.2.11
409
+ ONVIF Interactive Shell — v0.3.0
411
410
  https://github.com/nirsimetri/onvif-python
412
411
 
413
412
  Basic Commands:
@@ -502,7 +501,7 @@ If you omit the username or password, you will be prompted to enter them securel
502
501
  | `desc <method>` | Show documentation for a method |
503
502
  | `store <name>` | Store the last result with a variable name |
504
503
  | `show <name>` | Display a stored variable |
505
- | `exit` / `quit` | Exit the shell |
504
+ | `exit` | Exit the shell |
506
505
 
507
506
  > [!IMPORTANT]
508
507
  > You can see all the other commands available in the interactive shell by trying it out directly. The interactive shell runs periodic background health checks to detect connection loss. It uses silent TCP pings to avoid interrupting your work and will automatically exit if the device is unreachable, similar to an SSH session.
@@ -697,8 +696,9 @@ The `ONVIFClient` class provides various configuration options to customize the
697
696
  |-----------|------|----------|---------|-------------|
698
697
  | `host` | `str` | ✅ Yes | - | IP address or hostname of the ONVIF device (e.g., `"192.168.1.17"`) |
699
698
  | `port` | `int` | ✅ Yes | - | Port number for ONVIF service (common ports: `80`, `8000`, `8080`) |
700
- | `username` | `str` | ✅ Yes | - | Username for device authentication (use digest authentication) |
701
- | `password` | `str` | ✅ Yes | - | Password for device authentication |
699
+ | `username` | `str` | ❌ No | - | Username for device authentication |
700
+ | `password` | `str` | ❌ No | - | Password for device authentication |
701
+ | `http_digest` | `str` | ❌ No | `False` | `True` = use HTTP Digest / `False` = use WS-Usernametoken |
702
702
 
703
703
  </details>
704
704
 
@@ -709,7 +709,7 @@ The `ONVIFClient` class provides various configuration options to customize the
709
709
  |-----------|------|----------|---------|-------------|
710
710
  | `timeout` | `int` | ❌ No | `10` | Connection timeout in seconds for SOAP requests |
711
711
  | `use_https` | `bool` | ❌ No | `False` | Use HTTPS instead of HTTP for secure communication |
712
- | `verify_ssl` | `bool` | ❌ No | `True` | Verify SSL certificates when using HTTPS (set to `False` for self-signed certificates) |
712
+ | `verify_ssl` | `bool` | ❌ No | `False` | Verify SSL certificates when using HTTPS (set to `False` for self-signed certificates) |
713
713
 
714
714
  </details>
715
715
 
@@ -1099,11 +1099,11 @@ Some ONVIF services have multiple bindings in the same WSDL. These typically inc
1099
1099
  ```python
1100
1100
  client.security() # root binding
1101
1101
  client.jwt() # sub-binding accessor
1102
- client.authorizationserver(xaddr) # sub-binding accessor (requires xAddr)
1103
- client.keystore(xaddr) # ..
1104
- client.dot1x(xaddr)
1105
- client.tlsserver(xaddr)
1106
- client.mediasigning(xaddr)
1102
+ client.authorizationserver() # ..
1103
+ client.keystore()
1104
+ client.dot1x()
1105
+ client.tlsserver()
1106
+ client.mediasigning()
1107
1107
  ```
1108
1108
 
1109
1109
  3. **Analytics**
@@ -0,0 +1,25 @@
1
+ """ONVIF Python"""
2
+
3
+ from onvif.cli import main as ONVIFCLI
4
+ from onvif.client import ONVIFClient
5
+ from onvif.operator import CacheMode
6
+ from onvif.utils import (
7
+ ONVIFWSDL,
8
+ ONVIFDiscovery,
9
+ ONVIFErrorHandler,
10
+ ONVIFOperationException,
11
+ ONVIFParser,
12
+ ZeepPatcher,
13
+ )
14
+
15
+ __all__ = [
16
+ "ONVIFClient",
17
+ "CacheMode",
18
+ "ONVIFWSDL",
19
+ "ONVIFOperationException",
20
+ "ONVIFErrorHandler",
21
+ "ZeepPatcher",
22
+ "ONVIFCLI",
23
+ "ONVIFDiscovery",
24
+ "ONVIFParser",
25
+ ]
@@ -0,0 +1,5 @@
1
+ """ONVIF CLI."""
2
+
3
+ from onvif.cli.main import main
4
+
5
+ __all__ = ["main"]
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env python3
2
+ """ONVIF CLI entry point for python -m onvif.cli."""
3
+
4
+ from onvif.cli.main import main
5
+
6
+ if __name__ == "__main__":
7
+ main()
@@ -17,10 +17,7 @@ from typing import Any
17
17
  from requests.exceptions import RequestException
18
18
  from zeep.exceptions import Fault, TransportError
19
19
 
20
- from .. import __repository__, __version__
21
- from ..client import ONVIFClient
22
- from ..utils.exceptions import ONVIFOperationException
23
- from .utils import (
20
+ from onvif.cli.utils import (
24
21
  colorize,
25
22
  format_capabilities_as_services,
26
23
  format_services_list,
@@ -31,10 +28,13 @@ from .utils import (
31
28
  get_service_required_args,
32
29
  parse_json_params,
33
30
  )
31
+ from onvif.client import ONVIFClient
32
+ from onvif.meta import __repository__, __version__
33
+ from onvif.utils.exceptions import ONVIFOperationException
34
34
 
35
35
 
36
36
  class InteractiveShell(cmd.Cmd):
37
- """Interactive ONVIF CLI shell"""
37
+ """Interactive ONVIF CLI shell."""
38
38
 
39
39
  def __init__(self, client: ONVIFClient, args):
40
40
  super().__init__()
@@ -432,7 +432,7 @@ class InteractiveShell(cmd.Cmd):
432
432
  print(line)
433
433
 
434
434
  def _resolve_stored_reference(self, reference: str):
435
- """Resolve stored data reference like 'profiles[0].token' or 'profiles.Token'
435
+ """Resolve stored data reference like 'profiles[0].token' or 'profiles.Token'.
436
436
 
437
437
  Args:
438
438
  reference: String reference like 'profiles[0]' or 'profiles.Token'
@@ -440,7 +440,6 @@ class InteractiveShell(cmd.Cmd):
440
440
  Returns:
441
441
  Resolved value or None if not found
442
442
  """
443
-
444
443
  # Parse the reference - e.g., "profiles[0].token" or "services.Namespace"
445
444
  # Split by dots and brackets
446
445
  parts = re.split(r"\.|\[|\]", reference)
@@ -484,7 +483,7 @@ class InteractiveShell(cmd.Cmd):
484
483
  return current
485
484
 
486
485
  def _substitute_stored_references(self, params_str: str) -> str:
487
- """Substitute $variable references in parameter string with stored data
486
+ """Substitute $variable references in parameter string with stored data.
488
487
 
489
488
  Args:
490
489
  params_str: Parameter string that may contain $variable references
@@ -492,7 +491,6 @@ class InteractiveShell(cmd.Cmd):
492
491
  Returns:
493
492
  Parameter string with substituted values
494
493
  """
495
-
496
494
  # Find all $variable references (e.g., $profiles[0].token)
497
495
  pattern = (
498
496
  r"\$([a-zA-Z_][a-zA-Z0-9_]*(?:\[[0-9]+\])?(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*)"
@@ -518,14 +516,15 @@ class InteractiveShell(cmd.Cmd):
518
516
  return re.sub(pattern, replace_reference, params_str)
519
517
 
520
518
  def update_prompt(self):
521
- """Update command prompt based on current context"""
519
+ """Update command prompt based on current context."""
522
520
  if self.current_service_name:
523
521
  self.prompt = f"{self.args.username}@{self.args.host}:{self.args.port}/{self.current_service_name} > "
524
522
  else:
525
523
  self.prompt = f"{self.args.username}@{self.args.host}:{self.args.port} > "
526
524
 
527
525
  def onecmd(self, line):
528
- """Override onecmd to handle service method calls without showing cmd.Cmd traceback"""
526
+ """Override onecmd to handle service method calls without showing cmd.Cmd
527
+ traceback."""
529
528
  line = line.strip()
530
529
  if not line:
531
530
  return self.emptyline()
@@ -560,7 +559,7 @@ class InteractiveShell(cmd.Cmd):
560
559
  return super().onecmd(line)
561
560
 
562
561
  def default(self, line):
563
- """Handle unknown commands"""
562
+ """Handle unknown commands."""
564
563
  available_services = get_device_available_services(self.client)
565
564
 
566
565
  # Check if it's a service call (with or without arguments)
@@ -594,7 +593,7 @@ class InteractiveShell(cmd.Cmd):
594
593
  print(f"Type {colorize('help', 'white')} for available commands")
595
594
 
596
595
  def get_suggestions(self, partial_cmd: str) -> list[str]:
597
- """Get command suggestions based on partial input"""
596
+ """Get command suggestions based on partial input."""
598
597
  suggestions = []
599
598
 
600
599
  if self.current_service:
@@ -623,7 +622,7 @@ class InteractiveShell(cmd.Cmd):
623
622
  return suggestions[:5] # Limit to 5 suggestions
624
623
 
625
624
  def completenames(self, text: str, *ignored) -> list[str]:
626
- """Tab completion for command names"""
625
+ """Tab completion for command names."""
627
626
  if self.current_service:
628
627
  # Complete method names in service mode
629
628
  methods = get_service_methods(self.current_service)
@@ -646,7 +645,7 @@ class InteractiveShell(cmd.Cmd):
646
645
  return completions
647
646
 
648
647
  def cmdloop(self, intro=None):
649
- """Override cmdloop to handle TAB completion manually"""
648
+ """Override cmdloop to handle TAB completion manually."""
650
649
  if intro is not None:
651
650
  self.intro = intro
652
651
  if self.intro:
@@ -670,7 +669,7 @@ class InteractiveShell(cmd.Cmd):
670
669
  stop = self.postcmd(stop, line)
671
670
 
672
671
  def columnize(self, list, displaywidth=80):
673
- """Override columnize to use grid format for TAB completion"""
672
+ """Override columnize to use grid format for TAB completion."""
674
673
  if not list:
675
674
  return
676
675
 
@@ -678,7 +677,7 @@ class InteractiveShell(cmd.Cmd):
678
677
  self._display_grid(list)
679
678
 
680
679
  def print_topics(self, header, cmds, cmdlen, maxcol):
681
- """Override print_topics to use grid format for TAB completion"""
680
+ """Override print_topics to use grid format for TAB completion."""
682
681
  if not cmds:
683
682
  return
684
683
 
@@ -690,7 +689,7 @@ class InteractiveShell(cmd.Cmd):
690
689
  self._display_grid(cmds)
691
690
 
692
691
  def do_capabilities(self, line): # pylint: disable=unused-argument
693
- """Show device capabilities in service format"""
692
+ """Show device capabilities in service format."""
694
693
  try:
695
694
  if hasattr(self.client, "capabilities") and self.client.capabilities:
696
695
  result = self.client.capabilities
@@ -713,7 +712,7 @@ class InteractiveShell(cmd.Cmd):
713
712
  print(f"{colorize('Error:', 'red')} {e}")
714
713
 
715
714
  def do_services(self, line): # pylint: disable=unused-argument
716
- """Show available services in service format"""
715
+ """Show available services in service format."""
717
716
  try:
718
717
  if hasattr(self.client, "services") and self.client.services:
719
718
  result = self.client.services
@@ -736,7 +735,7 @@ class InteractiveShell(cmd.Cmd):
736
735
  print(f"{colorize('Error:', 'red')} {e}")
737
736
 
738
737
  def do_enter_service(self, line):
739
- """Enter service mode with optional arguments for services that require them"""
738
+ """Enter service mode with optional arguments for services that require them."""
740
739
  # Parse service name and arguments
741
740
  parts = line.split(None, 1)
742
741
  service_name = parts[0] if parts else ""
@@ -835,7 +834,7 @@ class InteractiveShell(cmd.Cmd):
835
834
  traceback.print_exc()
836
835
 
837
836
  def do_ls(self, line): # pylint: disable=unused-argument
838
- """List available commands/services like TAB completion"""
837
+ """List available commands/services like TAB completion."""
839
838
  if self.current_service:
840
839
  # In service mode - show available methods
841
840
  methods = get_service_methods(self.current_service)
@@ -859,7 +858,10 @@ class InteractiveShell(cmd.Cmd):
859
858
  print("No commands available")
860
859
 
861
860
  def do_desc(self, line):
862
- """Describes a method from its WSDL documentation. Usage: desc <method_name>"""
861
+ """Describes a method from its WSDL documentation.
862
+
863
+ Usage: desc <method_name>
864
+ """
863
865
  method_name = line.strip()
864
866
 
865
867
  if not self.current_service:
@@ -911,14 +913,17 @@ class InteractiveShell(cmd.Cmd):
911
913
  def complete_desc(
912
914
  self, text, line, begidx, endidx
913
915
  ): # pylint: disable=unused-argument
914
- """Autocomplete method names for desc command"""
916
+ """Autocomplete method names for desc command."""
915
917
  if not self.current_service:
916
918
  return []
917
919
  methods = get_service_methods(self.current_service)
918
920
  return [m for m in methods if m.lower().startswith(text.lower())]
919
921
 
920
922
  def do_type(self, line):
921
- """Show input and output types for a method. Usage: type <method_name>"""
923
+ """Show input and output types for a method.
924
+
925
+ Usage: type <method_name>
926
+ """
922
927
  method_name = line.strip()
923
928
 
924
929
  if not self.current_service:
@@ -944,8 +949,7 @@ class InteractiveShell(cmd.Cmd):
944
949
  if type_info:
945
950
  # Helper function to display parameters recursively with tree-style indentation
946
951
  def display_params(params, prefix_lines=None, is_root_level=False):
947
- """
948
- Display parameters with tree-style formatting.
952
+ """Display parameters with tree-style formatting.
949
953
 
950
954
  Args:
951
955
  params: List of parameter dictionaries
@@ -1003,7 +1007,10 @@ class InteractiveShell(cmd.Cmd):
1003
1007
  # Display parameter name with tree structure, prefix, occurrence, and type
1004
1008
  # Only add semicolon separator if there's an occurrence label
1005
1009
  separator = ";" if occurs else ""
1006
- param_line = f"{current_prefix}{tree_branch}{prefix_symbol}{colorize(param['name'], 'white')}{occurs}{separator} {colorize(type_str, 'cyan')}"
1010
+ param_line = (
1011
+ f"{current_prefix}{tree_branch}{prefix_symbol}{colorize(param['name'], 'white')}"
1012
+ f"{occurs}{separator} {colorize(type_str, 'cyan')}"
1013
+ )
1007
1014
  print(param_line)
1008
1015
 
1009
1016
  # Display documentation if available
@@ -1076,7 +1083,7 @@ class InteractiveShell(cmd.Cmd):
1076
1083
  def complete_type(
1077
1084
  self, text, line, begidx, endidx
1078
1085
  ): # pylint: disable=unused-argument
1079
- """Autocomplete method names for type command"""
1086
+ """Autocomplete method names for type command."""
1080
1087
  if not self.current_service:
1081
1088
  return []
1082
1089
  methods = get_service_methods(self.current_service)
@@ -1095,12 +1102,12 @@ class InteractiveShell(cmd.Cmd):
1095
1102
  def complete_cd(
1096
1103
  self, text, line, begidx, endidx
1097
1104
  ): # pylint: disable=unused-argument
1098
- """Autocomplete service names for cd command"""
1105
+ """Autocomplete service names for cd command."""
1099
1106
  services = get_device_available_services(self.client)
1100
1107
  return [s for s in services if s.lower().startswith(text.lower())]
1101
1108
 
1102
1109
  def do_pwd(self, line): # pylint: disable=unused-argument
1103
- """Show current service context"""
1110
+ """Show current service context."""
1104
1111
  if self.current_service_name:
1105
1112
  print(
1106
1113
  f"{colorize('Current service:', 'yellow')} {colorize(self.current_service_name, 'cyan')}"
@@ -1111,7 +1118,7 @@ class InteractiveShell(cmd.Cmd):
1111
1118
  )
1112
1119
 
1113
1120
  def do_shortcuts(self, line): # pylint: disable=unused-argument
1114
- """Show available shortcuts"""
1121
+ """Show available shortcuts."""
1115
1122
  shortcuts = f"""
1116
1123
  {colorize('Available Shortcuts:', 'cyan')}
1117
1124
 
@@ -1160,14 +1167,14 @@ class InteractiveShell(cmd.Cmd):
1160
1167
 
1161
1168
  def do_store(self, line):
1162
1169
  """Store last result with a name: store <name>"""
1163
-
1164
1170
  if not line:
1165
1171
  print("Usage: store <name>")
1166
1172
  return
1167
1173
  # Only allow valid Python variable names
1168
1174
  if not re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", line):
1169
1175
  print(
1170
- f"{colorize('Error:', 'red')} Invalid name '{line}'. Only letters, numbers, and underscores allowed, and must not start with a number."
1176
+ f"{colorize('Error:', 'red')} Invalid name '{line}'. "
1177
+ "Only letters, numbers, and underscores allowed, and must not start with a number."
1171
1178
  )
1172
1179
  return
1173
1180
  # Must be unique
@@ -1209,11 +1216,12 @@ class InteractiveShell(cmd.Cmd):
1209
1216
  def complete_rm(
1210
1217
  self, text, line, begidx, endidx
1211
1218
  ): # pylint: disable=unused-argument
1212
- """Autocomplete stored variable names for rm command"""
1219
+ """Autocomplete stored variable names for rm command."""
1213
1220
  return [name for name in self.stored_data if name.startswith(text)]
1214
1221
 
1215
1222
  def do_show(self, line):
1216
- """Show stored data: show <name> or show <name>.<attribute> or show <name>[index]"""
1223
+ """Show stored data: show <name> or show <name>.<attribute> or show
1224
+ <name>[index]"""
1217
1225
  if not line:
1218
1226
  print(colorize("Stored data:", "green"))
1219
1227
  for name in self.stored_data:
@@ -1235,7 +1243,7 @@ class InteractiveShell(cmd.Cmd):
1235
1243
  print(f"{colorize('Error:', 'red')} Cannot resolve '{line}'")
1236
1244
 
1237
1245
  def complete_show(self, text, line, begidx, endidx):
1238
- """Autocomplete stored variable names for show command"""
1246
+ """Autocomplete stored variable names for show command."""
1239
1247
  # Get the part being completed
1240
1248
  parts = line.split()
1241
1249
  if len(parts) <= 1 or (len(parts) == 2 and not line.endswith(" ")):
@@ -1244,18 +1252,18 @@ class InteractiveShell(cmd.Cmd):
1244
1252
  return []
1245
1253
 
1246
1254
  def do_clear(self, line): # pylint: disable=unused-argument
1247
- """Clear terminal screen"""
1255
+ """Clear terminal screen."""
1248
1256
  # Clear screen for both Windows and Unix-like systems
1249
1257
  os.system("cls" if os.name == "nt" else "clear")
1250
1258
 
1251
1259
  def do_cls(self, line): # pylint: disable=unused-argument
1252
- """Clear stored data"""
1260
+ """Clear stored data."""
1253
1261
  self.stored_data.clear()
1254
1262
  self.stored_metadata.clear()
1255
1263
  print(f"{colorize('Cleared all stored data', 'yellow')}")
1256
1264
 
1257
1265
  def do_info(self, line): # pylint: disable=unused-argument
1258
- """Show connection and device information"""
1266
+ """Show connection and device information."""
1259
1267
  # Build connection and CLI options info
1260
1268
  options_info = []
1261
1269
 
@@ -1305,7 +1313,7 @@ class InteractiveShell(cmd.Cmd):
1305
1313
  print() # Extra newline for spacing
1306
1314
 
1307
1315
  def execute_service_method(self, method_name, params_str):
1308
- """Execute a method on the current service"""
1316
+ """Execute a method on the current service."""
1309
1317
  if not self.current_service:
1310
1318
  print(f"{colorize('Error:', 'red')} Not in service mode")
1311
1319
  return
@@ -1359,7 +1367,7 @@ class InteractiveShell(cmd.Cmd):
1359
1367
  traceback.print_exc()
1360
1368
 
1361
1369
  def do_debug(self, line): # pylint: disable=unused-argument
1362
- """Show debug information"""
1370
+ """Show debug information."""
1363
1371
  if self.client.xml_plugin:
1364
1372
  if self._last_method and self._last_operation_timestamp:
1365
1373
  print(f"{colorize('Last Operation:', 'cyan')}")
@@ -1379,16 +1387,16 @@ class InteractiveShell(cmd.Cmd):
1379
1387
  )
1380
1388
 
1381
1389
  def do_exit(self, line): # pylint: disable=unused-argument
1382
- """Exit the shell"""
1390
+ """Exit the shell."""
1383
1391
  self._stop_health_check.set()
1384
1392
  print(colorize("Goodbye!", "cyan"))
1385
1393
  return True
1386
1394
 
1387
1395
  def emptyline(self):
1388
- """Handle empty line"""
1396
+ """Handle empty line."""
1389
1397
 
1390
1398
  def do_help(self, line):
1391
- """Show help information"""
1399
+ """Show help information."""
1392
1400
  if line:
1393
1401
  super().do_help(line)
1394
1402
  else:
@@ -1462,7 +1470,7 @@ class InteractiveShell(cmd.Cmd):
1462
1470
  print(help_text)
1463
1471
 
1464
1472
  def run(self):
1465
- """Run the interactive shell"""
1473
+ """Run the interactive shell."""
1466
1474
  try:
1467
1475
  self.cmdloop()
1468
1476
  except KeyboardInterrupt: