Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-ncclient for openSUSE:Factory 
checked in at 2024-11-11 14:58:22
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-ncclient (Old)
 and      /work/SRC/openSUSE:Factory/.python-ncclient.new.2017 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-ncclient"

Mon Nov 11 14:58:22 2024 rev:23 rq:1223349 version:0.6.16

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-ncclient/python-ncclient.changes  
2024-10-27 11:26:19.465014436 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-ncclient.new.2017/python-ncclient.changes    
    2024-11-11 14:58:25.567166739 +0100
@@ -1,0 +2,11 @@
+Sun Nov 10 19:50:09 UTC 2024 - Martin Hauke <mar...@gmx.de>
+
+- Update to version 0.6.16
+  * Add Ciena driver.
+  * Update session.py.
+  * call_home: timeout as argument.
+  * Introduce Unix Socket Transport.
+  * feat: Add support for Nokia SR OS private candidate mode.
+  * Fix support of .ssh/id_ed25519 keys.
+
+-------------------------------------------------------------------

Old:
----
  ncclient-0.6.15.tar.gz

New:
----
  ncclient-0.6.16.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-ncclient.spec ++++++
--- /var/tmp/diff_new_pack.5sh7Zx/_old  2024-11-11 14:58:27.323240211 +0100
+++ /var/tmp/diff_new_pack.5sh7Zx/_new  2024-11-11 14:58:27.351241382 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           python-ncclient
-Version:        0.6.15
+Version:        0.6.16
 Release:        0
 Summary:        Python library for NETCONF clients
 License:        Apache-2.0
@@ -75,7 +75,6 @@
 
 %install
 %python_install
-%python_expand rm -rf %{buildroot}%{$python_sitelib}/test
 %fdupes %{buildroot}
 
 %check

++++++ ncclient-0.6.15.tar.gz -> ncclient-0.6.16.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/README.md 
new/ncclient-0.6.16/README.md
--- old/ncclient-0.6.15/README.md       2023-10-16 17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/README.md       2024-10-09 10:17:14.000000000 +0200
@@ -19,6 +19,7 @@
 
 |  Date  | Release | Description |
 | :----: | :-----: | :---------- |
+| 10/18/23 | `0.6.15` | See [release 
page](https://github.com/ncclient/ncclient/releases/tag/v0.6.15)|
 | 04/10/22 | `0.6.13` | See [release 
page](https://github.com/ncclient/ncclient/releases/tag/v0.6.13)|
 | 05/29/21 | `0.6.12` | See [release 
page](https://github.com/ncclient/ncclient/releases/tag/v0.6.12)|
 | 05/27/21 | `0.6.11` | See [release 
page](https://github.com/ncclient/ncclient/releases/tag/v0.6.11)|
@@ -96,18 +97,19 @@
 
 When instantiating a connection to a known type of NETCONF server:
 
-* Juniper: `device_params={'name':'junos'}`
+* Alcatel Lucent: `device_params={'name':'alu'}`
+* Ciena: `device_params={'name':'ciena'}`
 * Cisco:
     - CSR: `device_params={'name':'csr'}`
     - Nexus: `device_params={'name':'nexus'}`
     - IOS XR: `device_params={'name':'iosxr'}`
     - IOS XE: `device_params={'name':'iosxe'}`
+* H3C: `device_params={'name':'h3c'}`
+* HP Comware: `device_params={'name':'hpcomware'}`
 * Huawei:
     - `device_params={'name':'huawei'}`
     - `device_params={'name':'huaweiyang'}`
-* Nokia SR OS: `device_params={'name':'sros'}`
-* H3C: `device_params={'name':'h3c'}`
-* HP Comware: `device_params={'name':'hpcomware'}`
+* Juniper: `device_params={'name':'junos'}`
 * Server or anything not in above: `device_params={'name':'default'}`
 
 
@@ -132,13 +134,18 @@
 1. Install testing dependencies:
 
     ```
-    pip install nose rednose coverage coveralls mock
+    pip install pytest coverage coveralls mock
     ```
 
 1. Finally, run the tests:
 
     ```
-    nosetests test --rednose --verbosity=3
+    pytest test --verbosity=3
+    ```
+    
+    For coverage, showing missing lines do:
+    ```
+    coverage run -m pytest test --verbosity=3 && coverage report -m
     ```
 
 ### Making a Release
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/README.rst 
new/ncclient-0.6.16/README.rst
--- old/ncclient-0.6.15/README.rst      2023-10-16 17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/README.rst      2024-10-09 10:17:14.000000000 +0200
@@ -87,18 +87,19 @@
 Supported device handlers
 '''''''''''''''''''''''''
 
-* Juniper: `device_params={'name':'junos'}`
+* Alcatel Lucent: `device_params={'name':'alu'}`
+* Ciena: `device_params={'name':'ciena'}`
 * Cisco:
     - CSR: `device_params={'name':'csr'}`
     - Nexus: `device_params={'name':'nexus'}`
     - IOS XR: `device_params={'name':'iosxr'}`
     - IOS XE: `device_params={'name':'iosxe'}`
+* H3C: `device_params={'name':'h3c'}`
+* HP Comware: `device_params={'name':'hpcomware'}`
 * Huawei:
     - `device_params={'name':'huawei'}`
     - `device_params={'name':'huaweiyang'}`
-* Nokia SR OS: `device_params={'name':'sros'}`
-* H3C: `device_params={'name':'h3c'}`
-* HP Comware: `device_params={'name':'hpcomware'}`
+* Juniper: `device_params={'name':'junos'}`
 * Server or anything not in above: `device_params={'name':'default'}`
 
 Changes \| brief
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/docs/source/index.rst 
new/ncclient-0.6.16/docs/source/index.rst
--- old/ncclient-0.6.15/docs/source/index.rst   2023-10-16 17:46:13.000000000 
+0200
+++ new/ncclient-0.6.16/docs/source/index.rst   2024-10-09 10:17:14.000000000 
+0200
@@ -39,18 +39,19 @@
 
 Supported device handlers
 -------------------------
-* Juniper: `device_params={'name':'junos'}`
+* Alcatel Lucent: `device_params={'name':'alu'}`
+* Ciena: `device_params={'name':'ciena'}`
 * Cisco:
     - CSR: `device_params={'name':'csr'}`
     - Nexus: `device_params={'name':'nexus'}`
     - IOS XR: `device_params={'name':'iosxr'}`
     - IOS XE: `device_params={'name':'iosxe'}`
+* H3C: `device_params={'name':'h3c'}`
+* HP Comware: `device_params={'name':'hpcomware'}`
 * Huawei:
     - `device_params={'name':'huawei'}`
     - `device_params={'name':'huaweiyang'}`
-* Alcatel Lucent: `device_params={'name':'alu'}`
-* H3C: `device_params={'name':'h3c'}`
-* HP Comware: `device_params={'name':'hpcomware'}`
+* Juniper: `device_params={'name':'junos'}`
 * Server or anything not in above: `device_params={'name':'default'}`
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/examples/base/nc10.py 
new/ncclient-0.6.16/examples/base/nc10.py
--- old/ncclient-0.6.15/examples/base/nc10.py   1970-01-01 01:00:00.000000000 
+0100
+++ new/ncclient-0.6.16/examples/base/nc10.py   2024-10-09 10:17:14.000000000 
+0200
@@ -0,0 +1,24 @@
+#! /usr/bin/env python
+#
+# Connect to NETCONF server using unix socket passed on the command line.
+# Then display the servers capabilities. After connecting you can also use 
+# all other operations supported by ncclient, example: get(), get_config()...
+#
+# To test against a example NETCONF server with unix socket support check out:
+# https://github.com/CESNET/libnetconf2
+# It contains an example server which can listen for connections using a unix 
+# socket.
+#
+# $ ./nc10.py "/path/to/socket"
+
+import sys, warnings
+warnings.simplefilter("ignore", DeprecationWarning)
+from ncclient import manager
+
+def demo(path):
+    with manager.connect_uds(path) as m:
+        for c in m.server_capabilities:
+            print(c)
+
+if __name__ == '__main__':
+    demo(sys.argv[1])
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ncclient-0.6.15/examples/vendor/nokia/sros/config_mode.py 
new/ncclient-0.6.16/examples/vendor/nokia/sros/config_mode.py
--- old/ncclient-0.6.15/examples/vendor/nokia/sros/config_mode.py       
1970-01-01 01:00:00.000000000 +0100
+++ new/ncclient-0.6.16/examples/vendor/nokia/sros/config_mode.py       
2024-10-09 10:17:14.000000000 +0200
@@ -0,0 +1,118 @@
+import logging
+import sys
+import threading
+import time
+from ncclient import manager
+
+# Device connection details
+DEVICE_HOST = '62.40.111.58'
+DEVICE_PORT = 3830
+DEVICE_USER = 'admin'
+DEVICE_PASS = 'admin'
+
+# Configuration payload template for SNMP community string
+EDIT_CONFIG_PAYLOAD = """
+<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <configure xmlns="urn:nokia.com:sros:ns:yang:sr:conf">
+        <system>
+            <security>
+                <snmp>
+                    <community>
+                        <community-string>TestCommunity-{}</community-string>
+                        <access-permissions>r</access-permissions>
+                        <version>v2c</version>
+                    </community>
+                </snmp>
+            </security>
+        </system>
+    </configure>
+</config>
+"""
+
+
+def create_ncclient_session(host, port, username, password, config_mode=None):
+    """
+    Creates and returns an ncclient manager session for connecting to the 
Nokia SR OS device.
+
+    :param host: Hostname or IP of the Nokia device
+    :param port: NETCONF port
+    :param username: Username for device authentication
+    :param password: Password for device authentication
+    :param config_mode: 'private' to use private candidate mode, None for 
default mode
+    :return: NETCONF manager session
+    """
+    device_params = {'name': 'sros'}
+    if config_mode:
+        device_params['config_mode'] = config_mode
+
+    return manager.connect(
+        host=host,
+        port=port,
+        username=username,
+        password=password,
+        hostkey_verify=False,
+        device_params=device_params
+    )
+
+
+def configure_and_commit(session_id, config_mode=None):
+    """
+    Creates a NETCONF session, edits the configuration, and commits the 
changes.
+
+    :param session_id: Unique session identifier for logging
+    :param config_mode: 'private' for private candidate mode, None for default 
mode
+    """
+    try:
+        with create_ncclient_session(DEVICE_HOST, DEVICE_PORT, DEVICE_USER, 
DEVICE_PASS, config_mode=config_mode) as nc_session:
+            logging.info(f"Session {session_id} started with config_mode: 
{config_mode or 'default'}")
+
+            # Edit the device configuration using the payload
+            edit_payload = EDIT_CONFIG_PAYLOAD.format(session_id)
+            nc_session.edit_config(target='candidate', config=edit_payload)
+            logging.info(f"Session {session_id} successfully edited the 
configuration.")
+
+            # Commit the changes to the device
+            nc_session.commit(comment=f"Session {session_id} commit in 
{config_mode or 'default'} mode")
+            logging.info(f"Session {session_id} committed successfully in 
{config_mode or 'default'} mode.")
+
+    except Exception as e:
+        logging.error(f"Session {session_id} encountered an error: {e}")
+
+
+def run_concurrent_sessions(session_ids, config_mode=None):
+    """
+    Runs multiple NETCONF sessions concurrently.
+
+    :param session_ids: List of session IDs to identify different threads
+    :param config_mode: 'private' to use private candidate mode, None for 
default mode
+    """
+    threads = []
+    for session_id in session_ids:
+        thread = threading.Thread(target=configure_and_commit, 
args=(session_id, config_mode))
+        threads.append(thread)
+        thread.start()
+
+    # Ensure all threads finish execution
+    for thread in threads:
+        thread.join()
+
+
+def main():
+    LOG_FORMAT = '%(asctime)s %(levelname)s %(filename)s:%(lineno)d 
%(message)s'
+    logging.basicConfig(stream=sys.stdout, level=logging.INFO, 
format=LOG_FORMAT)
+
+    logging.info("Starting test with concurrent sessions in default mode 
(expecting conflicts)...")
+
+    # Run test with concurrent sessions in default mode
+    run_concurrent_sessions([1, 2, 3, 4, 5])
+
+    logging.info("Now testing with concurrent sessions in private mode (no 
conflicts expected)...")
+
+    # Run test with concurrent sessions in private candidate mode
+    run_concurrent_sessions([6, 7, 8, 9], config_mode='private')
+
+    logging.info("Test completed.")
+
+
+if __name__ == '__main__':
+    main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/_version.py 
new/ncclient-0.6.16/ncclient/_version.py
--- old/ncclient-0.6.15/ncclient/_version.py    2023-10-16 17:46:13.000000000 
+0200
+++ new/ncclient-0.6.16/ncclient/_version.py    2024-10-09 10:17:14.000000000 
+0200
@@ -26,9 +26,9 @@
     # setup.py/versioneer.py will grep for the variable names, so they must
     # each be defined on a line of their own. _version.py will just call
     # get_keywords().
-    git_refnames = " (tag: v0.6.15)"
-    git_full = "f0f4d95ed8613f256f0972491d6c47f53246da0b"
-    git_date = "2023-10-16 16:46:13 +0100"
+    git_refnames = " (tag: v0.6.16)"
+    git_full = "652ef67b266df0ee02bbbbc4cc6eb09ca01f4878"
+    git_date = "2024-10-09 09:17:14 +0100"
     keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
     return keywords
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/devices/__init__.py 
new/ncclient-0.6.16/ncclient/devices/__init__.py
--- old/ncclient-0.6.15/ncclient/devices/__init__.py    2023-10-16 
17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/ncclient/devices/__init__.py    2024-10-09 
10:17:14.000000000 +0200
@@ -1,20 +1,24 @@
 # supported devices config, add new device (eg: 'device name':'device label').
-supported_devices_cfg = {'junos':'Juniper',
-                         'csr':'Cisco CSR1000v',
-                         'nexus':'Cisco Nexus',
-                         'iosxr':'Cisco IOS XR',
-                         'iosxe':'Cisco IOS XE',
-                         'huawei':'Huawei',
-                         'huaweiyang':'Huawei',
-                         'alu':'Alcatel Lucent',
-                         'h3c':'H3C',
-                         'hpcomware':'HP Comware',
-                         'sros':'Nokia SR OS',
-                         'default':'Server or anything not in above'}
+supported_devices_cfg = {
+    "alu": "Alcatel Lucent",
+    "ciena": "Ciena",
+    "csr": "Cisco CSR1000v",
+    "h3c": "H3C",
+    "hpcomware": "HP Comware",
+    "huawei": "Huawei",
+    "huaweiyang": "Huawei",
+    "iosxe": "Cisco IOS XE",
+    "iosxr": "Cisco IOS XR",
+    "junos": "Juniper",
+    "nexus": "Cisco Nexus",
+    "sros": "Nokia SR OS",
+    "default": "Server or anything not in above",
+}
+
 
 def get_supported_devices():
     return tuple(supported_devices_cfg.keys())
 
+
 def get_supported_device_labels():
     return supported_devices_cfg
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/devices/ciena.py 
new/ncclient-0.6.16/ncclient/devices/ciena.py
--- old/ncclient-0.6.15/ncclient/devices/ciena.py       1970-01-01 
01:00:00.000000000 +0100
+++ new/ncclient-0.6.16/ncclient/devices/ciena.py       2024-10-09 
10:17:14.000000000 +0200
@@ -0,0 +1,19 @@
+from .default import DefaultDeviceHandler
+from ncclient.xml_ import BASE_NS_1_0
+
+
+class CienaDeviceHandler(DefaultDeviceHandler):
+    """
+    Ciena handler for device specific information.
+    """
+
+    def __init__(self, device_params):
+        super(CienaDeviceHandler, self).__init__(device_params)
+
+    def get_xml_base_namespace_dict(self):
+        return {None: BASE_NS_1_0}
+
+    def get_xml_extra_prefix_kwargs(self):
+        d = {}
+        d.update(self.get_xml_base_namespace_dict())
+        return {"nsmap": d}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/devices/sros.py 
new/ncclient-0.6.16/ncclient/devices/sros.py
--- old/ncclient-0.6.15/ncclient/devices/sros.py        2023-10-16 
17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/ncclient/devices/sros.py        2024-10-09 
10:17:14.000000000 +0200
@@ -1,10 +1,11 @@
-from lxml import etree
-
 from .default import DefaultDeviceHandler
 from ncclient.operations.third_party.sros.rpc import MdCliRawCommand, Commit
 from ncclient.xml_ import BASE_NS_1_0
 
 
+class ConfigMode:
+    PRIVATE = 'private'
+
 def passthrough(xml):
     return xml
 
@@ -30,7 +31,11 @@
             'urn:ietf:params:xml:ns:netconf:base:1.0',
             'urn:ietf:params:xml:ns:yang:1',
             'urn:ietf:params:netconf:capability:confirmed-commit:1.1',
-            'urn:ietf:params:netconf:capability:validate:1.1']
+            'urn:ietf:params:netconf:capability:validate:1.1',
+        ]
+        if self.device_params.get('config_mode') == ConfigMode.PRIVATE:
+            additional.append('urn:nokia.com:nc:pc')
+
         return base + additional
 
     def get_xml_base_namespace_dict(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/manager.py 
new/ncclient-0.6.16/ncclient/manager.py
--- old/ncclient-0.6.15/ncclient/manager.py     2023-10-16 17:46:13.000000000 
+0200
+++ new/ncclient-0.6.16/ncclient/manager.py     2024-10-09 10:17:14.000000000 
+0200
@@ -158,6 +158,19 @@
 
     return Manager(session, device_handler, **manager_params)
 
+def connect_uds(*args, **kwargs):
+    """Initialize a :class:`Manager` over the Unix Socket transport."""
+    device_params = _extract_device_params(kwargs)
+    manager_params = _extract_manager_params(kwargs)
+    nc_params = _extract_nc_params(kwargs)
+
+    device_handler = make_device_handler(device_params)
+    device_handler.add_additional_netconf_params(nc_params)
+    session = transport.UnixSocketSession(device_handler)
+
+    session.connect(*args, **kwargs)
+
+    return Manager(session, device_handler, **manager_params)
 
 def connect_ioproc(*args, **kwds):
     device_params = _extract_device_params(kwds)
@@ -191,7 +204,7 @@
     port = kwds.get("port",4334)
     srv_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     srv_socket.bind((host, port))
-    srv_socket.settimeout(10)
+    srv_socket.settimeout(kwds.get("timeout", 10))
     srv_socket.listen()
 
     sock, remote_host = srv_socket.accept()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/transport/__init__.py 
new/ncclient-0.6.16/ncclient/transport/__init__.py
--- old/ncclient-0.6.15/ncclient/transport/__init__.py  2023-10-16 
17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/ncclient/transport/__init__.py  2024-10-09 
10:17:14.000000000 +0200
@@ -17,6 +17,7 @@
 from ncclient.transport.session import Session, SessionListener, NetconfBase
 from ncclient.transport.ssh import SSHSession
 from ncclient.transport.tls import TLSSession
+from ncclient.transport.unixSocket import UnixSocketSession
 from ncclient.transport.errors import *
 
 __all__ = [
@@ -24,6 +25,7 @@
     'SessionListener',
     'SSHSession',
     'TLSSession',
+    'UnixSocketSession',
     'TransportError',
     'AuthenticationError',
     'SessionCloseError',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/transport/errors.py 
new/ncclient-0.6.16/ncclient/transport/errors.py
--- old/ncclient-0.6.15/ncclient/transport/errors.py    2023-10-16 
17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/ncclient/transport/errors.py    2024-10-09 
10:17:14.000000000 +0200
@@ -53,3 +53,6 @@
 
 class TLSError(TransportError):
     pass
+
+class UnixSocketError (TransportError):
+    pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/transport/session.py 
new/ncclient-0.6.16/ncclient/transport/session.py
--- old/ncclient-0.6.15/ncclient/transport/session.py   2023-10-16 
17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/ncclient/transport/session.py   2024-10-09 
10:17:14.000000000 +0200
@@ -218,6 +218,21 @@
             self._transport_register(s, selectors.EVENT_READ)
             self.logger.debug('selector type = %s', s.__class__.__name__)
             while True:
+                
+                if not q.empty() and self._send_ready():
+                    self.logger.debug("Sending message")
+                    data = q.get().encode()
+                    if self._base == NetconfBase.BASE_11:
+                        data = b"%s%s%s" % (start_delim(len(data)), data, 
END_DELIM)
+                    else:
+                        data = b"%s%s" % (data, MSG_DELIM)
+                    self.logger.info("Sending:\n%s", data)
+                    while data:
+                        n = self._transport_write(data)
+                        if n <= 0:
+                            raise SessionCloseError(self._buffer.getvalue(), 
data)
+                        data = data[n:]
+                        
                 events = s.select(timeout=TICK)
                 if events:
                     data = self._transport_read()
@@ -234,19 +249,6 @@
                     else:
                         # End of session, unexpected
                         raise SessionCloseError(self._buffer.getvalue())
-                if not q.empty() and self._send_ready():
-                    self.logger.debug("Sending message")
-                    data = q.get().encode()
-                    if self._base == NetconfBase.BASE_11:
-                        data = b"%s%s%s" % (start_delim(len(data)), data, 
END_DELIM)
-                    else:
-                        data = b"%s%s" % (data, MSG_DELIM)
-                    self.logger.info("Sending:\n%s", data)
-                    while data:
-                        n = self._transport_write(data)
-                        if n <= 0:
-                            raise SessionCloseError(self._buffer.getvalue(), 
data)
-                        data = data[n:]
         except Exception as e:
             self.logger.debug("Broke out of main loop, error=%r", e)
             self._dispatch_error(e)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/transport/ssh.py 
new/ncclient-0.6.16/ncclient/transport/ssh.py
--- old/ncclient-0.6.15/ncclient/transport/ssh.py       2023-10-16 
17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/ncclient/transport/ssh.py       2024-10-09 
10:17:14.000000000 +0200
@@ -453,22 +453,28 @@
             rsa_key = os.path.expanduser("~/.ssh/id_rsa")
             dsa_key = os.path.expanduser("~/.ssh/id_dsa")
             ecdsa_key = os.path.expanduser("~/.ssh/id_ecdsa")
+            ed25519_key = os.path.expanduser("~/.ssh/id_ed25519")
             if os.path.isfile(rsa_key):
                 keyfiles.append((paramiko.RSAKey, rsa_key))
             if os.path.isfile(dsa_key):
                 keyfiles.append((paramiko.DSSKey, dsa_key))
             if os.path.isfile(ecdsa_key):
                 keyfiles.append((paramiko.ECDSAKey, ecdsa_key))
+            if os.path.isfile(ed25519_key):
+                keyfiles.append((paramiko.Ed25519Key, ed25519_key))
             # look in ~/ssh/ for windows users:
             rsa_key = os.path.expanduser("~/ssh/id_rsa")
             dsa_key = os.path.expanduser("~/ssh/id_dsa")
             ecdsa_key = os.path.expanduser("~/ssh/id_ecdsa")
+            ed25519_key = os.path.expanduser("~/ssh/id_ed25519")
             if os.path.isfile(rsa_key):
                 keyfiles.append((paramiko.RSAKey, rsa_key))
             if os.path.isfile(dsa_key):
                 keyfiles.append((paramiko.DSSKey, dsa_key))
             if os.path.isfile(ecdsa_key):
                 keyfiles.append((paramiko.ECDSAKey, ecdsa_key))
+            if os.path.isfile(ed25519_key):
+                keyfiles.append((paramiko.Ed25519Key, ed25519_key))
 
         for cls, filename in keyfiles:
             try:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/transport/unixSocket.py 
new/ncclient-0.6.16/ncclient/transport/unixSocket.py
--- old/ncclient-0.6.15/ncclient/transport/unixSocket.py        1970-01-01 
01:00:00.000000000 +0100
+++ new/ncclient-0.6.16/ncclient/transport/unixSocket.py        2024-10-09 
10:17:14.000000000 +0200
@@ -0,0 +1,83 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+import socket
+import threading
+from io import BytesIO as StringIO
+
+from socket import AF_UNIX, SOCK_STREAM
+
+from ncclient.capabilities import Capabilities
+from ncclient.logging_ import SessionLoggerAdapter
+from ncclient.transport.errors import UnixSocketError
+from ncclient.transport.session import Session
+from ncclient.transport.parser import DefaultXMLParser
+
+logger = logging.getLogger("ncclient.transport.unix")
+
+DEFAULT_TIMEOUT = 120
+
+BUF_SIZE = 4096
+
+class UnixSocketSession(Session):
+
+    "Implements a NETCONF Session over Unix Socket on local machine."
+
+    def __init__(self, device_handler):
+        capabilities = Capabilities(device_handler.get_capabilities())
+        Session.__init__(self, capabilities)
+        self._connected = False
+        self._socket = None
+        self._buffer = StringIO()
+        self._device_handler = device_handler
+        self._message_list = []
+        self._closing = threading.Event()
+        self.parser = DefaultXMLParser(self)
+        self.logger = SessionLoggerAdapter(logger, {'session': self})
+
+    def _dispatch_message(self, raw):
+        self.logger.info("Received message from host")
+        self.logger.debug("Received:\n%s", raw)
+        return super(UnixSocketSession, self)._dispatch_message(raw)
+
+    def close(self):
+        self._closing.set()
+        self._socket.close()
+        self._connected = False
+
+    def connect(self, path=None, timeout=DEFAULT_TIMEOUT):
+        sock = socket.socket(AF_UNIX, SOCK_STREAM)
+        sock.settimeout(timeout)
+
+        try:
+            sock.connect(path)
+        except Exception:
+            raise UnixSocketError("Could not connect to %s" % path)
+
+        self._socket = sock
+        self._connected = True
+        self._post_connect()
+
+    def _transport_read(self):
+        return self._socket.recv(BUF_SIZE)
+
+    def _transport_write(self, data):
+        return self._socket.send(data)
+
+    def _transport_register(self, selector, event):
+        selector.register(self._socket, event)
+
+    def _send_ready(self):
+        # In contrast to Paramiko's `Channel`, pure python sockets do not
+        # expose `send_ready()` function.
+        return True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/test/unit/devices/test_ciena.py 
new/ncclient-0.6.16/test/unit/devices/test_ciena.py
--- old/ncclient-0.6.15/test/unit/devices/test_ciena.py 1970-01-01 
01:00:00.000000000 +0100
+++ new/ncclient-0.6.16/test/unit/devices/test_ciena.py 2024-10-09 
10:17:14.000000000 +0200
@@ -0,0 +1,18 @@
+import unittest
+from ncclient.devices.ciena import *
+from ncclient.xml_ import *
+
+
+class TestCienaDevice(unittest.TestCase):
+    
+    def setUp(self):
+        self.obj = CienaDeviceHandler({'name': 'ciena'})
+
+    def test_get_xml_base_namespace_dict(self):
+        expected = {None: BASE_NS_1_0}
+        self.assertDictEqual(expected, self.obj.get_xml_base_namespace_dict())
+
+    def test_get_xml_extra_prefix_kwargs(self):
+        expected = dict()
+        expected["nsmap"] = self.obj.get_xml_base_namespace_dict()
+        self.assertDictEqual(expected, self.obj.get_xml_extra_prefix_kwargs())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ncclient-0.6.15/test/unit/devices/test_get_supported_devices.py 
new/ncclient-0.6.16/test/unit/devices/test_get_supported_devices.py
--- old/ncclient-0.6.15/test/unit/devices/test_get_supported_devices.py 
2023-10-16 17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/test/unit/devices/test_get_supported_devices.py 
2024-10-09 10:17:14.000000000 +0200
@@ -7,6 +7,7 @@
         supported_devices = devices.get_supported_devices()
         self.assertEqual(sorted(supported_devices), sorted(('junos',
                                                             'csr',
+                                                            'ciena',
                                                             'nexus',
                                                             'iosxr',
                                                             'iosxe',
@@ -22,6 +23,7 @@
         supported_device_labels = devices.get_supported_device_labels()
         self.assertEqual(supported_device_labels, {'junos':'Juniper',
                                                    'csr':'Cisco CSR1000v',
+                                                   'ciena': 'Ciena',
                                                    'nexus':'Cisco Nexus',
                                                    'iosxr':'Cisco IOS XR',
                                                    'iosxe':'Cisco IOS XE',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ncclient-0.6.15/test/unit/devices/test_sros.py 
new/ncclient-0.6.16/test/unit/devices/test_sros.py
--- old/ncclient-0.6.15/test/unit/devices/test_sros.py  2023-10-16 
17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/test/unit/devices/test_sros.py  2024-10-09 
10:17:14.000000000 +0200
@@ -1,7 +1,8 @@
 import unittest
 
-from ncclient.devices.sros import *
-from ncclient.xml_ import *
+from ncclient.devices.sros import SrosDeviceHandler, ConfigMode
+from ncclient.xml_ import to_ele, to_xml, BASE_NS_1_0
+from ncclient.operations.third_party.sros.rpc import MdCliRawCommand, Commit
 
 capabilities = ['urn:ietf:params:netconf:base:1.0',
                 'urn:ietf:params:netconf:base:1.1',
@@ -36,32 +37,39 @@
 class TestSrosDevice(unittest.TestCase):
 
     def setUp(self):
-        self.obj = SrosDeviceHandler({'name': 'sros'})
+        self.device_handler = SrosDeviceHandler({'name': 'sros'})
 
     def test_add_additional_operations(self):
         expected = {
             'md_cli_raw_command': MdCliRawCommand,
             'commit': Commit,
         }
-        self.assertDictEqual(expected, self.obj.add_additional_operations())
+        self.assertDictEqual(expected, 
self.device_handler.add_additional_operations())
 
     def test_transform_reply(self):
         expected = xml
-        actual = self.obj.transform_reply()
+        actual = self.device_handler.transform_reply()
         ele = to_ele(xml)
         self.assertEqual(expected, to_xml(actual(ele)))
 
-    def test_get_capabilities(self):
-        self.assertListEqual(capabilities, self.obj.get_capabilities())
+    def test_get_capabilities_without_config_mode(self):
+        """Test capabilities without 'config_mode' set"""
+        self.assertListEqual(capabilities, 
self.device_handler.get_capabilities())
+
+    def test_get_capabilities_with_config_mode_private(self):
+        """Test capabilities when 'config_mode' is set to 'private'"""
+        device_handler = SrosDeviceHandler({'name': 'sros', 'config_mode': 
ConfigMode.PRIVATE})
+        expected_capabilities = capabilities + ['urn:nokia.com:nc:pc']
+        self.assertListEqual(expected_capabilities, 
device_handler.get_capabilities())
 
     def test_get_xml_base_namespace_dict(self):
         expected = {None: BASE_NS_1_0}
-        self.assertDictEqual(expected, self.obj.get_xml_base_namespace_dict())
+        self.assertDictEqual(expected, 
self.device_handler.get_xml_base_namespace_dict())
 
     def test_get_xml_extra_prefix_kwargs(self):
         expected = dict()
-        expected['nsmap'] = self.obj.get_xml_base_namespace_dict()
-        self.assertDictEqual(expected, self.obj.get_xml_extra_prefix_kwargs())
+        expected['nsmap'] = self.device_handler.get_xml_base_namespace_dict()
+        self.assertDictEqual(expected, 
self.device_handler.get_xml_extra_prefix_kwargs())
 
     def test_perform_qualify_check(self):
-        self.assertFalse(self.obj.perform_qualify_check())
+        self.assertFalse(self.device_handler.perform_qualify_check())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ncclient-0.6.15/test/unit/transport/test_UnixSocket.py 
new/ncclient-0.6.16/test/unit/transport/test_UnixSocket.py
--- old/ncclient-0.6.15/test/unit/transport/test_UnixSocket.py  1970-01-01 
01:00:00.000000000 +0100
+++ new/ncclient-0.6.16/test/unit/transport/test_UnixSocket.py  2024-10-09 
10:17:14.000000000 +0200
@@ -0,0 +1,33 @@
+
+import sys
+import unittest
+import socket
+from ncclient.devices.junos import JunosDeviceHandler
+
+try:
+    from unittest.mock import MagicMock, patch, call
+except ImportError:
+    from mock import MagicMock, patch, call
+
+from ncclient.transport.errors import UnixSocketError
+from ncclient.transport.unixSocket import UnixSocketSession
+
+PATH = '/tmp/test_socket.sock'
+
+class TestUnixSocket(unittest.TestCase):
+
+    @patch('socket.socket.close')
+    def test_close_UnixSocket(self, mock_sock_close_fn):
+        session = UnixSocketSession(MagicMock())
+        session._socket = socket.socket()
+        session._connected = True
+        session.close()
+        mock_sock_close_fn.assert_called_once_with()
+        self.assertFalse(session.connected)
+
+    @patch('socket.socket')
+    @patch('ncclient.transport.Session._post_connect')
+    def test_connect_UnixSocket(self, mock_post_connect, mock_socket):
+        session = UnixSocketSession(MagicMock())
+        session.connect(path=PATH)
+        self.assertTrue(session.connected)

Reply via email to