Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-netmiko for openSUSE:Factory 
checked in at 2023-12-12 19:32:43
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-netmiko (Old)
 and      /work/SRC/openSUSE:Factory/.python-netmiko.new.25432 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-netmiko"

Tue Dec 12 19:32:43 2023 rev:21 rq:1132682 version:4.3.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-netmiko/python-netmiko.changes    
2023-08-28 17:17:21.413265197 +0200
+++ /work/SRC/openSUSE:Factory/.python-netmiko.new.25432/python-netmiko.changes 
2023-12-12 19:33:11.662595793 +0100
@@ -1,0 +2,42 @@
+Tue Dec 12 13:37:47 UTC 2023 - Dirk Müller <dmuel...@suse.com>
+
+- update to 4.3.0:
+  * Netmiko's session_log has certain scenarios where it was
+    failing to hide the default no_log items ("secret" and
+    "password"). This bug has generally been fixed though there
+    are likely edge scenarios where this could still happen.
+    Given the nature of the session_log it should always be
+    viewed as a security sensitive file.
+  * Drop PY3.7 support
+  * Improve Ciena SAOS logic in set_base_prompt
+  * Improve Nokia SROS disable paging behavior
+  * Remove Arris and Casa from SSH autodetect
+  * Add support for Genie and Linux
+  * Improve TP-Link session_preparation behavior
+  * Improve MikoTik terminal size definition
+  * Improve Arista SSH autodetection
+  * Fix SNMP autodetection when hostname is used (instead of
+    IPv4/IPv6 address)
+  * Improve SCP behavior for remote_file_size when subdirectories
+    are used
+  * Implement TelnetFallback entry point
+  * Improve Extreme SLX-OS autodetect
+  * Improve Fortinet driver _get_output_mode_v6 behavior
+  * Improve HP comware and HP procurve behavior in
+    session_preparation
+  * Add Allied Telesis in SNMP and SSH autodetect
+  * Update hp_comware.py handle RBM in prompt
+  * Update vyos_ssh.py to enter and exit config mode on save
+  * Handle Huawei secure configuration message
+  * Add support for a SessionLog object in dunder-init(). This
+    allows a custom no_log definition.
+  * CI-CD fixes for various things breaking
+  * Improve ers driver cntl-y behavior
+  * Adtran driver enable global_cmd_verify by default
+  * Adtran driver improve enable() behavior
+  * Add Telnet Proxy support for SOCKS Proxy
+  * Add support for Fiberstore FSOS
+  * Add support for Maipu
+  * Add Digi TransPort Router Support
+
+-------------------------------------------------------------------

Old:
----
  netmiko-4.2.0.tar.gz

New:
----
  netmiko-4.3.0.tar.gz

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

Other differences:
------------------
++++++ python-netmiko.spec ++++++
--- /var/tmp/diff_new_pack.fJgb0x/_old  2023-12-12 19:33:12.150613798 +0100
+++ /var/tmp/diff_new_pack.fJgb0x/_new  2023-12-12 19:33:12.154613945 +0100
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-netmiko
-Version:        4.2.0
+Version:        4.3.0
 Release:        0
 Summary:        Multi-vendor library to simplify Paramiko SSH connections to 
network devices
 License:        MIT

++++++ netmiko-4.2.0.tar.gz -> netmiko-4.3.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/PKG-INFO new/netmiko-4.3.0/PKG-INFO
--- old/netmiko-4.2.0/PKG-INFO  1970-01-01 01:00:00.000000000 +0100
+++ new/netmiko-4.3.0/PKG-INFO  1970-01-01 01:00:00.000000000 +0100
@@ -1,22 +1,21 @@
 Metadata-Version: 2.1
 Name: netmiko
-Version: 4.2.0
+Version: 4.3.0
 Summary: Multi-vendor library to simplify legacy CLI connections to network 
devices
 Home-page: https://github.com/ktbyers/netmiko
 License: MIT
 Author: Kirk Byers
 Author-email: ktby...@twb-tech.com
-Requires-Python: >=3.7,<4.0
+Requires-Python: >=3.8,<4.0
 Classifier: License :: OSI Approved :: MIT License
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
-Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.12
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
 Requires-Dist: ntc-templates (>=2.0.0)
@@ -30,7 +29,7 @@
 
 [![PyPI - Python 
Version](https://img.shields.io/pypi/pyversions/netmiko.svg)](https://img.shields.io/pypi/pyversions/netmiko)
 
[![PyPI](https://img.shields.io/pypi/v/netmiko.svg)](https://pypi.python.org/pypi/netmiko)
-[![Downloads](https://pepy.tech/badge/netmiko)](https://pepy.tech/project/netmiko)
+[![Downloads](https://static.pepy.tech/badge/netmiko)](https://static.pepy.tech/badge/netmiko)
 [![GitHub 
contributors](https://img.shields.io/github/contributors/ktbyers/netmiko.svg)](https://GitHub.com/ktbyers/netmiko/graphs/contributors/)
 [![Code 
Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)
 
@@ -43,6 +42,12 @@
 
 <br />
 
+## Contributing to Netmiko
+
+[CONTRIBUTING.md](https://github.com/ktbyers/netmiko/blob/develop/CONTRIBUTING.md)
+
+<br />
+
 ## Why Netmiko?
 Network automation to screen-scraping devices is primarily concerned with 
gathering output from show commands and with making configuration changes.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/README.md new/netmiko-4.3.0/README.md
--- old/netmiko-4.2.0/README.md 2023-05-05 18:30:15.008753300 +0200
+++ new/netmiko-4.3.0/README.md 2023-11-17 18:35:13.596568000 +0100
@@ -1,6 +1,6 @@
 [![PyPI - Python 
Version](https://img.shields.io/pypi/pyversions/netmiko.svg)](https://img.shields.io/pypi/pyversions/netmiko)
 
[![PyPI](https://img.shields.io/pypi/v/netmiko.svg)](https://pypi.python.org/pypi/netmiko)
-[![Downloads](https://pepy.tech/badge/netmiko)](https://pepy.tech/project/netmiko)
+[![Downloads](https://static.pepy.tech/badge/netmiko)](https://static.pepy.tech/badge/netmiko)
 [![GitHub 
contributors](https://img.shields.io/github/contributors/ktbyers/netmiko.svg)](https://GitHub.com/ktbyers/netmiko/graphs/contributors/)
 [![Code 
Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)
 
@@ -13,6 +13,12 @@
 
 <br />
 
+## Contributing to Netmiko
+
+[CONTRIBUTING.md](https://github.com/ktbyers/netmiko/blob/develop/CONTRIBUTING.md)
+
+<br />
+
 ## Why Netmiko?
 Network automation to screen-scraping devices is primarily concerned with 
gathering output from show commands and with making configuration changes.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/__init__.py 
new/netmiko-4.3.0/netmiko/__init__.py
--- old/netmiko-4.2.0/netmiko/__init__.py       2023-05-05 18:30:15.060753600 
+0200
+++ new/netmiko-4.3.0/netmiko/__init__.py       2023-11-17 18:35:13.604568000 
+0100
@@ -1,9 +1,9 @@
 import sys
 
-__version__ = "4.2.0"
+__version__ = "4.3.0"
 PY_MAJ_VER = 3
-PY_MIN_VER = 7
-MIN_PYTHON_VER = "3.7"
+PY_MIN_VER = 8
+MIN_PYTHON_VER = "3.8"
 
 
 # Make sure user is using a valid Python version (for Netmiko)
@@ -38,6 +38,7 @@
 
 
 from netmiko.ssh_dispatcher import ConnectHandler  # noqa
+from netmiko.ssh_dispatcher import TelnetFallback  # noqa
 from netmiko.ssh_dispatcher import ConnLogOnly  # noqa
 from netmiko.ssh_dispatcher import ConnUnify  # noqa
 from netmiko.ssh_dispatcher import ssh_dispatcher  # noqa
@@ -66,6 +67,7 @@
 
 __all__ = (
     "ConnectHandler",
+    "AgnosticHandler",
     "ConnLogOnly",
     "ConnUnify",
     "ssh_dispatcher",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/adtran/adtran.py 
new/netmiko-4.3.0/netmiko/adtran/adtran.py
--- old/netmiko-4.2.0/netmiko/adtran/adtran.py  2023-05-05 18:30:15.060753600 
+0200
+++ new/netmiko-4.3.0/netmiko/adtran/adtran.py  2023-11-17 18:35:13.604568000 
+0100
@@ -1,16 +1,12 @@
 from typing import Any, Optional
 import re
 from netmiko.cisco_base_connection import CiscoBaseConnection
+from netmiko.exceptions import NetmikoTimeoutException
 
 
 class AdtranOSBase(CiscoBaseConnection):
     prompt_pattern = r"[>#]"
 
-    def __init__(self, *args: Any, **kwargs: Any) -> None:
-        if kwargs.get("global_cmd_verify") is None:
-            kwargs["global_cmd_verify"] = False
-        return super().__init__(*args, **kwargs)
-
     def session_preparation(self) -> None:
         """Prepare the session after the connection has been established."""
         self.ansi_escape_codes = True
@@ -31,14 +27,55 @@
         check_state: bool = True,
         re_flags: int = re.IGNORECASE,
     ) -> str:
-        return super().enable(
-            cmd=cmd,
-            pattern=pattern,
-            enable_pattern=enable_pattern,
-            check_state=check_state,
-            re_flags=re_flags,
+        output = ""
+        msg = (
+            "Failed to enter enable mode. Please ensure you pass "
+            "the 'secret' argument to ConnectHandler."
         )
 
+        # Check if in enable mode already.
+        if check_state and self.check_enable_mode():
+            return output
+
+        # Send "enable" mode command
+        self.write_channel(self.normalize_cmd(cmd))
+        try:
+            # Read the command echo
+            if self.global_cmd_verify is not False:
+                output += 
self.read_until_pattern(pattern=re.escape(cmd.strip()))
+
+            # Search for trailing prompt or password pattern
+            output += self.read_until_prompt_or_pattern(
+                pattern=pattern, re_flags=re_flags
+            )
+
+            # Send the "secret" in response to password pattern
+            if re.search(pattern, output):
+                self.write_channel(self.normalize_cmd(self.secret))
+
+                # Handle the fallback to local authentication case
+                fallback_pattern = r"Falling back"
+                new_output = self.read_until_prompt_or_pattern(
+                    pattern=fallback_pattern, re_flags=re_flags
+                )
+                output += new_output
+
+                if "Falling back" in new_output:
+                    self.write_channel(self.normalize_cmd(self.secret))
+                    output += self.read_until_prompt()
+
+            # Search for terminating pattern if defined
+            if enable_pattern and not re.search(enable_pattern, output):
+                output += self.read_until_pattern(pattern=enable_pattern)
+            else:
+                if not self.check_enable_mode():
+                    raise ValueError(msg)
+
+        except NetmikoTimeoutException:
+            raise ValueError(msg)
+
+        return output
+
     def exit_enable_mode(self, exit_command: str = "disable") -> str:
         return super().exit_enable_mode(exit_command=exit_command)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/base_connection.py 
new/netmiko-4.3.0/netmiko/base_connection.py
--- old/netmiko-4.2.0/netmiko/base_connection.py        2023-05-05 
18:30:15.068753700 +0200
+++ new/netmiko-4.3.0/netmiko/base_connection.py        2023-11-17 
18:35:13.608568000 +0100
@@ -61,6 +61,7 @@
     calc_old_timeout,
 )
 from netmiko.utilities import m_exec_time  # noqa
+from netmiko import telnet_proxy
 
 if TYPE_CHECKING:
     from os import PathLike
@@ -102,6 +103,20 @@
     return cast(F, wrapper_decorator)
 
 
+def flush_session_log(func: F) -> F:
+    @functools.wraps(func)
+    def wrapper_decorator(self: "BaseConnection", *args: Any, **kwargs: Any) 
-> Any:
+        try:
+            return_val = func(self, *args, **kwargs)
+        finally:
+            # Always flush the session_log
+            if self.session_log:
+                self.session_log.flush()
+        return return_val
+
+    return cast(F, wrapper_decorator)
+
+
 def log_writes(func: F) -> F:
     """Handle both session_log and log of writes."""
 
@@ -181,6 +196,7 @@
         allow_auto_change: bool = False,
         encoding: str = "utf-8",
         sock: Optional[socket.socket] = None,
+        sock_telnet: Optional[Dict[str, Any]] = None,
         auto_connect: bool = True,
         delay_factor_compat: bool = False,
         disable_lf_normalization: bool = False,
@@ -267,7 +283,8 @@
                 to select smallest of global and specific. Sets default 
global_delay_factor to .1
                 (default: True)
 
-        :param session_log: File path or BufferedIOBase subclass object to 
write the session log to.
+        :param session_log: File path, SessionLog object, or BufferedIOBase 
subclass object
+                to write the session log to.
 
         :param session_log_record_writes: The session log generally only 
records channel reads due
                 to eliminate command duplication due to command echo. You can 
enable this if you
@@ -280,11 +297,14 @@
                 (default: False)
 
         :param encoding: Encoding to be used when writing bytes to the output 
channel.
-                (default: ascii)
+                (default: "utf-8")
 
         :param sock: An open socket or socket-like object (such as a 
`.Channel`) to use for
                 communication to the target host (default: None).
 
+        :param sock_telnet: A dictionary of telnet socket parameters (SOCKS 
proxy). See
+                telnet_proxy.py code for details.
+
         :param global_cmd_verify: Control whether command echo verification is 
enabled or disabled
                 (default: None). Global attribute takes precedence over 
function `cmd_verify`
                 argument. Value of `None` indicates to use function 
`cmd_verify` argument.
@@ -351,6 +371,7 @@
         self.allow_auto_change = allow_auto_change
         self.encoding = encoding
         self.sock = sock
+        self.sock_telnet = sock_telnet
         self.fast_cli = fast_cli
         self._legacy_mode = _legacy_mode
         self.global_delay_factor = global_delay_factor
@@ -366,6 +387,7 @@
             no_log["password"] = self.password
         if self.secret:
             no_log["secret"] = self.secret
+        # Always sanitize username and password
         log.addFilter(SecretsFilter(no_log=no_log))
 
         # Netmiko will close the session_log if we open the file
@@ -386,10 +408,14 @@
                     no_log=no_log,
                     record_writes=session_log_record_writes,
                 )
+            elif isinstance(session_log, SessionLog):
+                # SessionLog object
+                self.session_log = session_log
+                self.session_log.open()
             else:
                 raise ValueError(
                     "session_log must be a path to a file, a file handle, "
-                    "or a BufferedIOBase subclass."
+                    "SessionLog object, or a BufferedIOBase subclass."
                 )
 
         # Default values
@@ -667,7 +693,6 @@
         start_time = time.time()
         # if read_timeout == 0 or 0.0 keep reading indefinitely
         while (time.time() - start_time < read_timeout) or (not read_timeout):
-
             output += self.read_channel()
 
             if re.search(pattern, output, flags=re_flags):
@@ -1084,9 +1109,17 @@
         """
         self.channel: Channel
         if self.protocol == "telnet":
-            self.remote_conn = telnetlib.Telnet(
-                self.host, port=self.port, timeout=self.timeout
-            )
+            if self.sock_telnet:
+                self.remote_conn = telnet_proxy.Telnet(
+                    self.host,
+                    port=self.port,
+                    timeout=self.timeout,
+                    proxy_dict=self.sock_telnet,
+                )
+            else:
+                self.remote_conn = telnetlib.Telnet(
+                    self.host, port=self.port, timeout=self.timeout
+                )
             # Migrating communication to channel class
             self.channel = TelnetChannel(conn=self.remote_conn, 
encoding=self.encoding)
             self.telnet_login()
@@ -1447,7 +1480,6 @@
         return output
 
     def command_echo_read(self, cmd: str, read_timeout: float) -> str:
-
         # Make sure you read until you detect the command echo (avoid getting 
out of sync)
         new_data = self.read_until_pattern(
             pattern=re.escape(cmd), read_timeout=read_timeout
@@ -1464,6 +1496,7 @@
             pass
         return new_data
 
+    @flush_session_log
     @select_cmd_verify
     def send_command_timing(
         self,
@@ -1612,6 +1645,7 @@
             prompt = self.base_prompt
         return re.escape(prompt.strip())
 
+    @flush_session_log
     @select_cmd_verify
     def send_command(
         self,
@@ -2135,6 +2169,7 @@
             commands = cfg_file.readlines()
         return self.send_config_set(commands, **kwargs)
 
+    @flush_session_log
     def send_config_set(
         self,
         config_commands: Union[str, Sequence[str], Iterator[str], TextIO, 
None] = None,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/ciena/ciena_saos.py 
new/netmiko-4.3.0/netmiko/ciena/ciena_saos.py
--- old/netmiko-4.2.0/netmiko/ciena/ciena_saos.py       2023-05-05 
18:30:15.072753700 +0200
+++ new/netmiko-4.3.0/netmiko/ciena/ciena_saos.py       2023-11-17 
18:35:13.608568000 +0100
@@ -28,7 +28,7 @@
         prompt = self.find_prompt(delay_factor=delay_factor)
 
         pattern = rf"^.+{self.prompt_pattern}$"
-        if re.search(pattern, prompt):
+        if not re.search(pattern, prompt):
             raise ValueError(f"Router prompt not found: {repr(prompt)}")
         # Strip off trailing terminator
         self.base_prompt = prompt[:-1]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/digi/__init__.py 
new/netmiko-4.3.0/netmiko/digi/__init__.py
--- old/netmiko-4.2.0/netmiko/digi/__init__.py  1970-01-01 01:00:00.000000000 
+0100
+++ new/netmiko-4.3.0/netmiko/digi/__init__.py  2023-11-17 18:35:13.608568000 
+0100
@@ -0,0 +1,3 @@
+from netmiko.digi.digi_transport import DigiTransportSSH
+
+__all__ = ["DigiTransportSSH"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/digi/digi_transport.py 
new/netmiko-4.3.0/netmiko/digi/digi_transport.py
--- old/netmiko-4.2.0/netmiko/digi/digi_transport.py    1970-01-01 
01:00:00.000000000 +0100
+++ new/netmiko-4.3.0/netmiko/digi/digi_transport.py    2023-11-17 
18:35:13.608568000 +0100
@@ -0,0 +1,27 @@
+"""Digi TransPort Routers"""
+from typing import Any
+from netmiko.no_enable import NoEnable
+from netmiko.no_config import NoConfig
+from netmiko.cisco_base_connection import CiscoSSHConnection
+
+
+class DigiTransportBase(NoEnable, NoConfig, CiscoSSHConnection):
+    def __init__(self, *args: Any, **kwargs: Any) -> None:
+        default_enter = kwargs.get("default_enter")
+        kwargs["default_enter"] = "\r\n" if default_enter is None else 
default_enter
+        super().__init__(*args, **kwargs)
+
+    def save_config(
+        self,
+        cmd: str = "config 0 save",
+        confirm: bool = False,
+        confirm_response: str = "",
+    ) -> str:
+        output = self._send_command_str(
+            command_string=cmd, expect_string="Please wait..."
+        )
+        return output
+
+
+class DigiTransportSSH(DigiTransportBase):
+    pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/extreme/extreme_ers_ssh.py 
new/netmiko-4.3.0/netmiko/extreme/extreme_ers_ssh.py
--- old/netmiko-4.2.0/netmiko/extreme/extreme_ers_ssh.py        2023-05-05 
18:30:15.076753600 +0200
+++ new/netmiko-4.3.0/netmiko/extreme/extreme_ers_ssh.py        2023-11-17 
18:35:13.608568000 +0100
@@ -2,6 +2,7 @@
 import re
 from netmiko.cisco_base_connection import CiscoSSHConnection
 from netmiko.exceptions import NetmikoAuthenticationException
+import time
 
 # Extreme ERS presents Enter Ctrl-Y to begin.
 CTRL_Y = "\x19"
@@ -27,6 +28,10 @@
 
         Older devices the Ctrl-Y is before SSH-login (not 100% sure of this).
 
+        Few devices after SSH-login the Ctrl-Y turns to blank screen-no 
pattern \
+
+        prompt appears after Enter/Return ( tested ).
+
         Newer devices this is after SSH-login.
         """
 
@@ -46,6 +51,9 @@
 
             if cntl_y in new_data:
                 self.write_channel(CTRL_Y)
+                time.sleep(1 * delay_factor)
+                # no pattern, blank for few devices till Return keypress
+                self.write_channel(self.RETURN)
             elif "Press ENTER" in new_data:
                 self.write_channel(self.RETURN)
             elif uname in new_data:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/fiberstore/__init__.py 
new/netmiko-4.3.0/netmiko/fiberstore/__init__.py
--- old/netmiko-4.2.0/netmiko/fiberstore/__init__.py    1970-01-01 
01:00:00.000000000 +0100
+++ new/netmiko-4.3.0/netmiko/fiberstore/__init__.py    2023-11-17 
18:35:13.612568100 +0100
@@ -0,0 +1,3 @@
+from netmiko.fiberstore.fiberstore_fsos import FiberstoreFsosSSH
+
+__all__ = ["FiberstoreFsosSSH"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/fiberstore/fiberstore_fsos.py 
new/netmiko-4.3.0/netmiko/fiberstore/fiberstore_fsos.py
--- old/netmiko-4.2.0/netmiko/fiberstore/fiberstore_fsos.py     1970-01-01 
01:00:00.000000000 +0100
+++ new/netmiko-4.3.0/netmiko/fiberstore/fiberstore_fsos.py     2023-11-17 
18:35:13.612568100 +0100
@@ -0,0 +1,108 @@
+"""Fiberstore FSOS Driver."""
+from typing import Optional
+from paramiko import SSHClient
+from netmiko.ssh_auth import SSHClient_noauth
+from netmiko.no_enable import NoEnable
+import time
+from os import path
+from netmiko.cisco_base_connection import CiscoSSHConnection
+from netmiko.exceptions import NetmikoAuthenticationException
+
+
+class FiberstoreFsosSSH(NoEnable, CiscoSSHConnection):
+    """
+    Fiberstore FSOS uses a non-standard SSH login mechanism. Consequently,
+    to make the login work, we have to override the SSHClient _auth method.
+    """
+
+    def session_preparation(self) -> None:
+        """Prepare the session after the connection has been established."""
+        self.ansi_escape_codes = True
+        output = self._test_channel_read()
+        if "% Authentication Failed" in output:
+            assert self.remote_conn is not None
+            self.remote_conn.close()
+            msg = f"Login failed: {self.host}"
+            raise NetmikoAuthenticationException(msg)
+
+        self.set_base_prompt()
+        self.disable_paging(command="terminal length 0")
+        # Clear the read buffer
+        time.sleep(0.3 * self.global_delay_factor)
+        self.clear_buffer()
+
+    def set_base_prompt(
+        self,
+        pri_prompt_terminator: str = ">",
+        alt_prompt_terminator: str = "#",
+        delay_factor: float = 1.0,
+        pattern: Optional[str] = None,
+    ) -> str:
+        prompt = super().set_base_prompt(
+            pri_prompt_terminator=pri_prompt_terminator,
+            alt_prompt_terminator=alt_prompt_terminator,
+            delay_factor=delay_factor,
+            pattern=pattern,
+        )
+        prompt = prompt.strip()
+        self.base_prompt = prompt
+        return self.base_prompt
+
+    def check_config_mode(
+        self,
+        check_string: str = "(config)#",
+        pattern: str = "",
+        force_regex: bool = False,
+    ) -> bool:
+        return super().check_config_mode(
+            check_string=check_string, pattern=pattern, force_regex=force_regex
+        )
+
+    def config_mode(
+        self, config_command: str = "config", pattern: str = "", re_flags: int 
= 0
+    ) -> str:
+        return super().config_mode(
+            config_command=config_command, pattern=pattern, re_flags=re_flags
+        )
+
+    def _build_ssh_client(self) -> SSHClient:
+        """Allows you to bypass standard SSH auth while still supporting SSH 
keys."""
+
+        # If user does not provide SSH key, we use noauth
+        remote_conn_pre: SSHClient
+        if not self.use_keys:
+            remote_conn_pre = SSHClient_noauth()
+        else:
+            remote_conn_pre = SSHClient()
+
+        # Load host_keys for better SSH security
+        if self.system_host_keys:
+            remote_conn_pre.load_system_host_keys()
+        if self.alt_host_keys and path.isfile(self.alt_key_file):
+            remote_conn_pre.load_host_keys(self.alt_key_file)
+
+        # Default is to automatically add untrusted hosts (make sure 
appropriate for your env)
+        remote_conn_pre.set_missing_host_key_policy(self.key_policy)
+        return remote_conn_pre
+
+    def special_login_handler(self, delay_factor: float = 1.0) -> None:
+        """
+        Fiberstore S3200 presents with the following on login
+        Username:
+        Password: ****
+        """
+        delay_factor = self.select_delay_factor(delay_factor)
+        i = 0
+        output = ""
+        while i <= 12:
+            i += 1
+            time.sleep(delay_factor)
+            output = self.read_channel()
+            if output:
+                if "Username:" in output:
+                    assert self.username is not None
+                    self.write_channel(self.username + self.RETURN)
+                elif "Password:" in output:
+                    assert self.password is not None
+                    self.write_channel(self.password + self.RETURN)
+                    return
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/fortinet/fortinet_ssh.py 
new/netmiko-4.3.0/netmiko/fortinet/fortinet_ssh.py
--- old/netmiko-4.2.0/netmiko/fortinet/fortinet_ssh.py  2023-05-05 
18:30:15.080753800 +0200
+++ new/netmiko-4.3.0/netmiko/fortinet/fortinet_ssh.py  2023-11-17 
18:35:13.612568100 +0100
@@ -148,13 +148,7 @@
         if self._vdoms:
             self._config_global()
 
-        self._send_command_str(
-            "config system console", expect_string=self.prompt_pattern
-        )
-        output = self._send_command_str(
-            "show full-configuration", expect_string=self.prompt_pattern
-        )
-        self._send_command_str("end", expect_string=self.prompt_pattern)
+        output = self._send_command_str("show full-configuration system 
console")
 
         if self._vdoms:
             self._exit_config_global()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/hp/hp_comware.py 
new/netmiko-4.3.0/netmiko/hp/hp_comware.py
--- old/netmiko-4.2.0/netmiko/hp/hp_comware.py  2023-05-05 18:30:15.080753800 
+0200
+++ new/netmiko-4.3.0/netmiko/hp/hp_comware.py  2023-11-17 18:35:13.612568100 
+0100
@@ -22,7 +22,7 @@
             self._test_channel_read(pattern=r"[>\]]")
 
         self.set_base_prompt()
-        command = self.RETURN + "screen-length disable"
+        command = "screen-length disable"
         self.disable_paging(command=command)
 
     def config_mode(
@@ -98,6 +98,9 @@
             pattern=pattern,
         )
 
+        # Strip off any leading RBM_. characters for firewall HA
+        prompt = re.sub(r"^RBM_.", "", prompt, flags=re.M)
+
         # Strip off leading character
         prompt = prompt[1:]
         prompt = prompt.strip()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/hp/hp_procurve.py 
new/netmiko-4.3.0/netmiko/hp/hp_procurve.py
--- old/netmiko-4.2.0/netmiko/hp/hp_procurve.py 2023-05-05 18:30:15.080753800 
+0200
+++ new/netmiko-4.3.0/netmiko/hp/hp_procurve.py 2023-11-17 18:35:13.612568100 
+0100
@@ -59,7 +59,7 @@
         # ProCurve requires elevated privileges to disable output paging :-(
         self.enable()
         self.set_terminal_width(command="terminal width 511", 
pattern="terminal")
-        command = self.RETURN + "no page"
+        command = "no page"
         self.disable_paging(command=command)
 
     def check_config_mode(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/huawei/huawei.py 
new/netmiko-4.3.0/netmiko/huawei/huawei.py
--- old/netmiko-4.2.0/netmiko/huawei/huawei.py  2023-05-05 18:30:15.080753800 
+0200
+++ new/netmiko-4.3.0/netmiko/huawei/huawei.py  2023-11-17 18:35:13.616568000 
+0100
@@ -151,6 +151,16 @@
             self.write_channel("N" + self.RETURN)
             self.read_until_pattern(pattern=self.prompt_pattern)
 
+        # Huawei prompts for secure the configuration before displaying the 
initial base prompt.
+        if re.search(
+            r"security\srisks\sin\sthe\sconfiguration\sfile.*\[y\/n\]", data, 
flags=re.I
+        ):
+            self.send_command("Y", expect_string=r"(?i)continue.*\[y\/n\]")
+            self.send_command(
+                "Y", expect_string=r"saved\ssuccessfully", read_timeout=60
+            )
+            self.read_until_pattern(pattern=self.prompt_pattern)
+
 
 class HuaweiTelnet(HuaweiBase):
     """Huawei Telnet driver."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/maipu/__init__.py 
new/netmiko-4.3.0/netmiko/maipu/__init__.py
--- old/netmiko-4.2.0/netmiko/maipu/__init__.py 1970-01-01 01:00:00.000000000 
+0100
+++ new/netmiko-4.3.0/netmiko/maipu/__init__.py 2023-11-17 18:35:13.616568000 
+0100
@@ -0,0 +1,4 @@
+from netmiko.maipu.maipu import MaipuSSH
+from netmiko.maipu.maipu import MaipuTelnet
+
+__all__ = ["MaipuSSH", "MaipuTelnet"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/maipu/maipu.py 
new/netmiko-4.3.0/netmiko/maipu/maipu.py
--- old/netmiko-4.2.0/netmiko/maipu/maipu.py    1970-01-01 01:00:00.000000000 
+0100
+++ new/netmiko-4.3.0/netmiko/maipu/maipu.py    2023-11-17 18:35:13.616568000 
+0100
@@ -0,0 +1,35 @@
+import time
+
+from netmiko.cisco_base_connection import CiscoBaseConnection
+
+
+class MaipuBase(CiscoBaseConnection):
+    def session_preparation(self) -> None:
+        """Prepare the session after the connection has been established."""
+        self._test_channel_read(pattern=r"[>#]")
+        self.set_base_prompt()
+        self.enable()
+        self.disable_paging(command="more off")
+        # Clear the read buffer
+        time.sleep(0.3 * self.global_delay_factor)
+        self.clear_buffer()
+
+    def save_config(
+        self, cmd: str = "write", confirm: bool = False, confirm_response: str 
= ""
+    ) -> str:
+        """Saves Config Using Copy Run Start"""
+        return super().save_config(
+            cmd=cmd, confirm=confirm, confirm_response=confirm_response
+        )
+
+
+class MaipuSSH(MaipuBase):
+    """MAIPU SSH driver"""
+
+    pass
+
+
+class MaipuTelnet(MaipuBase):
+    """MAIPU telnet driver"""
+
+    pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/mikrotik/mikrotik_ssh.py 
new/netmiko-4.3.0/netmiko/mikrotik/mikrotik_ssh.py
--- old/netmiko-4.2.0/netmiko/mikrotik/mikrotik_ssh.py  2023-05-05 
18:30:15.084753800 +0200
+++ new/netmiko-4.3.0/netmiko/mikrotik/mikrotik_ssh.py  2023-11-17 
18:35:13.616568000 +0100
@@ -39,10 +39,10 @@
         c: disable console colors
         e: enable dumb terminal mode
         t: disable auto detect terminal capabilities
-        w511: set term width
-        h4098: set term height
+        511w: set term width
+        4098h: set term height
         """
-        self.username += "+ctw511h4098"
+        self.username += "+ct511w4098h"
 
     def disable_paging(self, *args: Any, **kwargs: Any) -> str:
         """Mikrotik does not have paging by default."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/nokia/nokia_sros.py 
new/netmiko-4.3.0/netmiko/nokia/nokia_sros.py
--- old/netmiko-4.2.0/netmiko/nokia/nokia_sros.py       2023-05-05 
18:30:15.084753800 +0200
+++ new/netmiko-4.3.0/netmiko/nokia/nokia_sros.py       2023-11-17 
18:35:13.616568000 +0100
@@ -48,7 +48,6 @@
                 command="environment console width 512", pattern="environment"
             )
             self.disable_paging(command="environment more false")
-            # To perform file operations we need to disable paging in 
classical-CLI also
             self.disable_paging(command="//environment no more")
         else:
             # Classical CLI has no method to set the terminal width nor to 
disable command
@@ -56,6 +55,8 @@
             # Only disabled if not set under the ConnectHandler.
             if self.global_cmd_verify is None:
                 self.global_cmd_verify = False
+            # Disable paging in both modes, file operations require no paging 
in classic
+            self.disable_paging(command="//environment more false")
             self.disable_paging(command="environment no more", 
pattern="environment")
 
         # Clear the read buffer
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/scp_handler.py 
new/netmiko-4.3.0/netmiko/scp_handler.py
--- old/netmiko-4.2.0/netmiko/scp_handler.py    2023-05-05 18:30:15.088753700 
+0200
+++ new/netmiko-4.3.0/netmiko/scp_handler.py    2023-11-17 18:35:13.620568000 
+0100
@@ -271,7 +271,8 @@
         remote_out = "".join(remote_out_lines)
         # Match line containing file name
         assert isinstance(remote_file, str)
-        escape_file_name = re.escape(remote_file)
+        remote_file_base = os.path.basename(remote_file)
+        escape_file_name = re.escape(remote_file_base)
         pattern = r".*({}).*".format(escape_file_name)
         match = re.search(pattern, remote_out)
         if match:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/session_log.py 
new/netmiko-4.3.0/netmiko/session_log.py
--- old/netmiko-4.2.0/netmiko/session_log.py    2023-05-05 18:30:15.088753700 
+0200
+++ new/netmiko-4.3.0/netmiko/session_log.py    2023-11-17 18:35:13.620568000 
+0100
@@ -12,6 +12,7 @@
         file_encoding: str = "utf-8",
         no_log: Optional[Dict[str, Any]] = None,
         record_writes: bool = False,
+        slog_buffer: Optional[io.StringIO] = None,
     ) -> None:
         if no_log is None:
             self.no_log = {}
@@ -30,6 +31,13 @@
         else:
             self.session_log = None
 
+        # In order to ensure all the no_log entries get hidden properly,
+        # we must first store everying in memory and then write out to file.
+        # Otherwise, we might miss the data we are supposed to hide (since
+        # the no_log data potentially spans multiple reads).
+        if slog_buffer is None:
+            self.slog_buffer = io.StringIO()
+
         # Ensures last write operations prior to disconnect are recorded.
         self.fin = False
 
@@ -49,15 +57,30 @@
 
     def close(self) -> None:
         """Close the session_log file (if it is a file that we opened)."""
+        self.flush()
         if self.session_log and self._session_log_close:
             self.session_log.close()
             self.session_log = None
 
-    def write(self, data: str) -> None:
-        if self.session_log is not None and len(data) > 0:
-            # Hide the password and secret in the session_log
-            for hidden_data in self.no_log.values():
-                data = data.replace(hidden_data, "********")
+    def no_log_filter(self, data: str) -> str:
+        """Filter content from the session_log."""
+        for hidden_data in self.no_log.values():
+            data = data.replace(hidden_data, "********")
+        return data
+
+    def _read_buffer(self) -> str:
+        self.slog_buffer.seek(0)
+        data = self.slog_buffer.read()
+        # Once read, create a new buffer
+        self.slog_buffer = io.StringIO()
+        return data
+
+    def flush(self) -> None:
+        """Force the slog_buffer to be written out to the actual file"""
+
+        if self.session_log is not None:
+            data = self._read_buffer()
+            data = self.no_log_filter(data)
 
             if isinstance(self.session_log, io.BufferedIOBase):
                 self.session_log.write(write_bytes(data, 
encoding=self.file_encoding))
@@ -67,4 +90,10 @@
             assert isinstance(self.session_log, io.BufferedIOBase) or 
isinstance(
                 self.session_log, io.TextIOBase
             )
+
+            # Flush the underlying file
             self.session_log.flush()
+
+    def write(self, data: str) -> None:
+        if len(data) > 0:
+            self.slog_buffer.write(data)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/snmp_autodetect.py 
new/netmiko-4.3.0/netmiko/snmp_autodetect.py
--- old/netmiko-4.2.0/netmiko/snmp_autodetect.py        2023-05-05 
18:30:15.088753700 +0200
+++ new/netmiko-4.3.0/netmiko/snmp_autodetect.py        2023-11-17 
18:35:13.620568000 +0100
@@ -20,10 +20,10 @@
 Note, pysnmp is a required dependency for SNMPDetect and is intentionally not 
included in
 netmiko requirements. So installation of pysnmp might be required.
 """
-import ipaddress
-from typing import Optional, Dict
+from typing import Optional, Dict, List
 from typing.re import Pattern
 import re
+import socket
 
 try:
     from pysnmp.entity.rfc3413.oneliner import cmdgen
@@ -40,6 +40,11 @@
         "expr": re.compile(r".*Arista Networks EOS.*", re.IGNORECASE),
         "priority": 99,
     },
+    "allied_telesis_awplus": {
+        "oid": ".1.3.6.1.2.1.1.1.0",
+        "expr": re.compile(r".*AlliedWare Plus.*", re.IGNORECASE),
+        "priority": 99,
+    },
     "paloalto_panos": {
         "oid": ".1.3.6.1.2.1.1.1.0",
         "expr": re.compile(r".*Palo Alto Networks.*", re.IGNORECASE),
@@ -130,6 +135,51 @@
         SNMP_MAPPER[device_type] = SNMP_MAPPER_BASE[device_type]
 
 
+def identify_address_type(entry: str) -> List[str]:
+    """
+    Return a list containing all ip types found. An empty list means no valid 
ip were found
+    Parameters
+    ----------
+    entry: str
+        Can be an ipv4, an ipv6 or an FQDN.
+
+    Returns
+    -------
+    list of string: list
+        A list of string 'IPv4' | 'IPv6' which indicates if entry is a valid 
ipv4 and/or ipv6.
+    """
+    try:
+        socket.inet_pton(socket.AF_INET, entry)
+        return ["IPv4"]
+    except socket.error:
+        pass
+
+    try:
+        socket.inet_pton(socket.AF_INET6, entry)
+        return ["IPv6"]
+    except socket.error:
+        pass
+
+    ip_types = []
+    try:
+        addrinfo = socket.getaddrinfo(entry, None)
+        for info in addrinfo:
+            ip = info[4][0]
+            try:
+                socket.inet_pton(socket.AF_INET, ip)
+                ip_types.append("IPv4")
+            except socket.error:
+                pass
+            try:
+                socket.inet_pton(socket.AF_INET6, ip)
+                ip_types.append("IPv6")
+            except socket.error:
+                pass
+    except socket.gaierror:
+        pass
+    return ip_types
+
+
 class SNMPDetect(object):
     """
     The SNMPDetect class tries to automatically determine the device type.
@@ -197,7 +247,6 @@
         auth_proto: str = "sha",
         encrypt_proto: str = "aes128",
     ) -> None:
-
         # Check that the SNMP version is matching predefined type or raise 
ValueError
         if snmp_version == "v1" or snmp_version == "v2c":
             if not community:
@@ -245,7 +294,7 @@
         self._response_cache: Dict[str, str] = {}
         self.snmp_target = (self.hostname, self.snmp_port)
 
-        if ipaddress.ip_address(self.hostname).version == 6:
+        if "IPv6" in identify_address_type(self.hostname):
             self.udp_transport_target = cmdgen.Udp6TransportTarget(
                 self.snmp_target, timeout=1.5, retries=2
             )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/ssh_autodetect.py 
new/netmiko-4.3.0/netmiko/ssh_autodetect.py
--- old/netmiko-4.2.0/netmiko/ssh_autodetect.py 2023-05-05 18:30:15.088753700 
+0200
+++ new/netmiko-4.3.0/netmiko/ssh_autodetect.py 2023-11-17 18:35:13.620568000 
+0100
@@ -64,27 +64,21 @@
         "priority": 99,
         "dispatch": "_autodetect_std",
     },
-    "apresia_aeos": {
-        "cmd": "show system",
-        "search_patterns": ["Apresia"],
-        "priority": 99,
-        "dispatch": "_autodetect_std",
-    },
-    "arista_eos": {
+    "allied_telesis_awplus": {
         "cmd": "show version",
-        "search_patterns": [r"Arista"],
+        "search_patterns": ["AlliedWare Plus"],
         "priority": 99,
         "dispatch": "_autodetect_std",
     },
-    "arris_cer": {
-        "cmd": "show version",
-        "search_patterns": [r"CER"],
+    "apresia_aeos": {
+        "cmd": "show system",
+        "search_patterns": ["Apresia"],
         "priority": 99,
         "dispatch": "_autodetect_std",
     },
-    "casa_cmts": {
+    "arista_eos": {
         "cmd": "show version",
-        "search_patterns": [r"Casa"],
+        "search_patterns": [r"Arista", r"vEOS"],
         "priority": 99,
         "dispatch": "_autodetect_std",
     },
@@ -230,7 +224,9 @@
     },
     "extreme_slx": {
         "cmd": "show version",
-        "search_patterns": [r"SLX-OS Operating System Software"],
+        "search_patterns": [
+            r"SLX-OS Operating System",
+        ],
         "priority": 99,
         "dispatch": "_autodetect_std",
     },
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/ssh_dispatcher.py 
new/netmiko-4.3.0/netmiko/ssh_dispatcher.py
--- old/netmiko-4.2.0/netmiko/ssh_dispatcher.py 2023-05-05 18:30:15.092754000 
+0200
+++ new/netmiko-4.3.0/netmiko/ssh_dispatcher.py 2023-11-17 18:35:13.620568000 
+0100
@@ -1,6 +1,7 @@
 """Controls selection of proper class based on the device type."""
 from typing import Any, Type, Optional
 from typing import TYPE_CHECKING
+import re
 from netmiko.exceptions import ConnectionException
 from netmiko.exceptions import NetmikoTimeoutException, 
NetmikoAuthenticationException
 from netmiko.a10 import A10SSH
@@ -56,6 +57,7 @@
 from netmiko.dell import DellPowerConnectSSH
 from netmiko.dell import DellPowerConnectTelnet
 from netmiko.dell import DellIsilonSSH
+from netmiko.digi import DigiTransportSSH
 from netmiko.dlink import DlinkDSTelnet, DlinkDSSSH
 from netmiko.eltex import EltexSSH, EltexEsrSSH
 from netmiko.endace import EndaceSSH
@@ -77,8 +79,10 @@
 from netmiko.extreme import ExtremeWingSSH
 from netmiko.f5 import F5TmshSSH
 from netmiko.f5 import F5LinuxSSH
+from netmiko.fiberstore import FiberstoreFsosSSH
 from netmiko.flexvnf import FlexvnfSSH
 from netmiko.fortinet import FortinetSSH
+from netmiko.hillstone import HillstoneStoneosSSH
 from netmiko.hp import HPProcurveSSH, HPProcurveTelnet, HPComwareSSH, 
HPComwareTelnet
 from netmiko.huawei import HuaweiSSH, HuaweiVrpv8SSH, HuaweiTelnet
 from netmiko.huawei import HuaweiSmartAXSSH
@@ -87,6 +91,8 @@
 from netmiko.juniper import JuniperFileTransfer
 from netmiko.keymile import KeymileSSH, KeymileNOSSSH
 from netmiko.linux import LinuxSSH, LinuxFileTransfer
+from netmiko.maipu import MaipuSSH
+from netmiko.maipu import MaipuTelnet
 from netmiko.mikrotik import MikrotikRouterOsSSH, MikrotikRouterOsFileTransfer
 from netmiko.mikrotik import MikrotikSwitchOsSSH
 from netmiko.mellanox import MellanoxMlnxosSSH
@@ -131,7 +137,7 @@
 from netmiko.supermicro import SmciSwitchSmisSSH
 from netmiko.supermicro import SmciSwitchSmisTelnet
 from netmiko.zyxel import ZyxelSSH
-from netmiko.hillstone import HillstoneStoneosSSH
+
 
 if TYPE_CHECKING:
     from netmiko.base_connection import BaseConnection
@@ -196,6 +202,7 @@
     "dell_powerconnect": DellPowerConnectSSH,
     "dell_isilon": DellIsilonSSH,
     "dlink_ds": DlinkDSSSH,
+    "digi_transport": DigiTransportSSH,
     "endace": EndaceSSH,
     "eltex": EltexSSH,
     "eltex_esr": EltexEsrSSH,
@@ -216,6 +223,7 @@
     "f5_ltm": F5TmshSSH,
     "f5_tmsh": F5TmshSSH,
     "f5_linux": F5LinuxSSH,
+    "fiberstore_fsos": FiberstoreFsosSSH,
     "flexvnf": FlexvnfSSH,
     "fortinet": FortinetSSH,
     "generic": GenericSSH,
@@ -260,6 +268,7 @@
     "supermicro_smis": SmciSwitchSmisSSH,
     "teldat_cit": TeldatCITSSH,
     "tplink_jetstream": TPLinkJetStreamSSH,
+    # ubiquiti_airos - Placeholder agreed to with NTC (if this driver is 
created in future)
     "ubiquiti_edge": UbiquitiEdgeSSH,
     "ubiquiti_edgerouter": UbiquitiEdgeRouterSSH,
     "ubiquiti_edgeswitch": UbiquitiEdgeSSH,
@@ -270,6 +279,7 @@
     "zte_zxros": ZteZxrosSSH,
     "yamaha": YamahaSSH,
     "zyxel_os": ZyxelSSH,
+    "maipu": MaipuSSH,
 }
 
 FILE_TRANSFER_MAP = {
@@ -347,6 +357,7 @@
 CLASS_MAPPER["tplink_jetstream_telnet"] = TPLinkJetStreamTelnet
 CLASS_MAPPER["yamaha_telnet"] = YamahaTelnet
 CLASS_MAPPER["zte_zxros_telnet"] = ZteZxrosTelnet
+CLASS_MAPPER["maipu_telnet"] = MaipuTelnet
 
 # Add serial drivers
 CLASS_MAPPER["cisco_ios_serial"] = CiscoIosSerial
@@ -388,6 +399,24 @@
     return ConnectionClass(*args, **kwargs)
 
 
+def TelnetFallback(*args: Any, **kwargs: Any) -> "BaseConnection":
+    """If an SSH connection fails, try to fallback to Telnet."""
+    try:
+        return ConnectHandler(*args, **kwargs)
+    except (NetmikoTimeoutException, ConnectionRefusedError):
+        device_type = kwargs["device_type"]
+        # platforms_str is the base form (i.e. does not have the '_ssh' suffix)
+        if device_type in platforms_str:
+            alternative_device = f"{device_type}_telnet"
+        elif "_ssh" in device_type:
+            alternative_device = re.sub("_ssh", "_telnet", device_type)
+
+        if alternative_device in platforms:
+            kwargs["device_type"] = alternative_device
+            return ConnectHandler(*args, **kwargs)
+        raise
+
+
 def ConnLogOnly(
     log_file: str = "netmiko.log",
     log_level: Optional[int] = None,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/telnet_proxy.py 
new/netmiko-4.3.0/netmiko/telnet_proxy.py
--- old/netmiko-4.2.0/netmiko/telnet_proxy.py   1970-01-01 01:00:00.000000000 
+0100
+++ new/netmiko-4.3.0/netmiko/telnet_proxy.py   2023-11-17 18:35:13.624568200 
+0100
@@ -0,0 +1,61 @@
+from typing import Dict, Any, Optional
+import socket
+import telnetlib
+
+try:
+    import socks
+
+    SOCKS_SUPPORTED = True
+except ModuleNotFoundError:
+    SOCKS_SUPPORTED = False
+
+
+class Telnet(telnetlib.Telnet):
+    def __init__(
+        self,
+        host: Optional[str] = None,
+        port: int = 0,
+        timeout: float = socket._GLOBAL_DEFAULT_TIMEOUT,  # type: ignore
+        proxy_dict: Optional[Dict[str, Any]] = None,
+    ) -> None:
+        self.proxy_dict = proxy_dict
+        super().__init__(host=host, port=port, timeout=timeout)
+
+    def open(
+        self,
+        host: str,
+        port: int = 0,
+        timeout: float = socket._GLOBAL_DEFAULT_TIMEOUT,  # type: ignore
+    ) -> None:
+        """
+        Connect to a host.
+        The optional second argument is the port number, which
+        defaults to the standard telnet port (23).
+
+        Don't try to reopen an already connected instance.
+
+        proxy_dict = {
+                'proxy_type': socks.SOCKS5,
+                'proxy_addr': hostname,
+                'proxy_port': port,
+                'proxy_username': username,
+                'proxy_password': password
+            }
+        """
+        self.eof = 0
+        if not port:
+            port = telnetlib.TELNET_PORT
+        self.host = host
+        self.port = port
+        self.timeout = timeout
+
+        if SOCKS_SUPPORTED:
+            self.sock = socks.create_connection(
+                (host, port), timeout, **self.proxy_dict
+            )
+        else:
+            msg = """
+In order to use the telnet socks proxy, you must 'pip install pysocks'. Note, 
pysocks is
+unmaintained (so use at your own risk).
+"""
+            raise ModuleNotFoundError(msg)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/tplink/tplink_jetstream.py 
new/netmiko-4.3.0/netmiko/tplink/tplink_jetstream.py
--- old/netmiko-4.2.0/netmiko/tplink/tplink_jetstream.py        2023-05-05 
18:30:15.092754000 +0200
+++ new/netmiko-4.3.0/netmiko/tplink/tplink_jetstream.py        2023-11-17 
18:35:13.624568200 +0100
@@ -21,15 +21,12 @@
         return super().__init__(**kwargs)
 
     def session_preparation(self) -> None:
-        """
-        Prepare the session after the connection has been established.
-        """
         delay_factor = self.select_delay_factor(delay_factor=0)
         time.sleep(0.3 * delay_factor)
-        self.clear_buffer()
         self._test_channel_read(pattern=r"[>#]")
         self.set_base_prompt()
         self.enable()
+        self.set_base_prompt()
         self.disable_paging()
         # Clear the read buffer
         time.sleep(0.3 * self.global_delay_factor)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/utilities.py 
new/netmiko-4.3.0/netmiko/utilities.py
--- old/netmiko-4.2.0/netmiko/utilities.py      2022-08-09 23:16:34.350460500 
+0200
+++ new/netmiko-4.3.0/netmiko/utilities.py      2023-11-17 18:35:13.624568200 
+0100
@@ -499,7 +499,7 @@
         )
         raise ValueError(msg)
 
-    if "cisco" not in platform:
+    if "cisco" not in platform and "linux" not in platform:
         return raw_output
 
     genie_device_mapper = {
@@ -508,6 +508,9 @@
         "cisco_xr": "iosxr",
         "cisco_nxos": "nxos",
         "cisco_asa": "asa",
+        "linux": "linux",
+        "f5_linux": "linux",
+        "ovs_linux": "linux",
     }
 
     os = None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/netmiko/vyos/vyos_ssh.py 
new/netmiko-4.3.0/netmiko/vyos/vyos_ssh.py
--- old/netmiko-4.2.0/netmiko/vyos/vyos_ssh.py  2022-08-09 23:16:34.350460500 
+0200
+++ new/netmiko-4.3.0/netmiko/vyos/vyos_ssh.py  2023-11-17 18:35:13.624568200 
+0100
@@ -136,9 +136,11 @@
         self, cmd: str = "save", confirm: bool = False, confirm_response: str 
= ""
     ) -> str:
         """Saves Config."""
-        output = super().save_config(
+        output = self.config_mode()
+        output += super().save_config(
             cmd=cmd, confirm=confirm, confirm_response=confirm_response
         )
+        output += self.exit_config_mode()
         if "Done" not in output:
             raise ValueError(f"Save failed with following errors:\n\n{output}")
         return output
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/pyproject.toml 
new/netmiko-4.3.0/pyproject.toml
--- old/netmiko-4.2.0/pyproject.toml    2023-05-05 18:30:15.100753800 +0200
+++ new/netmiko-4.3.0/pyproject.toml    2023-11-17 18:35:13.628568200 +0100
@@ -4,7 +4,7 @@
 
 [tool.poetry]
 name = "netmiko"
-version = "4.2.0"
+version = "4.3.0"
 description = "Multi-vendor library to simplify legacy CLI connections to 
network devices"
 authors = ["Kirk Byers <ktby...@twb-tech.com>"]
 license = "MIT"
@@ -12,15 +12,15 @@
 repository = "https://github.com/ktbyers/netmiko";
 classifiers = [
         "License :: OSI Approved :: MIT License",
-        "Programming Language :: Python :: 3.7",
         "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",
+        "Programming Language :: Python :: 3.12",
 ]
 
 [tool.poetry.dependencies]
-python = ">=3.7,<4.0"
+python = ">=3.8,<4.0"
 paramiko = ">=2.9.5"
 scp = ">=0.13.6"
 pyyaml = ">=5.3"
@@ -32,7 +32,7 @@
 black = "22.3.0"
 mypy = "1.0.0"
 mypy-extensions = "1.0.0"
-PyYAML = "5.4.1"
+PyYAML = "6.0.1"
 pytest = "7.1.2"
 # Issue with build failure on pyflakes 2.5.0
 pyflakes = "2.4.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/netmiko-4.2.0/setup.py new/netmiko-4.3.0/setup.py
--- old/netmiko-4.2.0/setup.py  1970-01-01 01:00:00.000000000 +0100
+++ new/netmiko-4.3.0/setup.py  1970-01-01 01:00:00.000000000 +0100
@@ -28,6 +28,7 @@
  'netmiko.cloudgenix',
  'netmiko.coriant',
  'netmiko.dell',
+ 'netmiko.digi',
  'netmiko.dlink',
  'netmiko.eltex',
  'netmiko.endace',
@@ -35,6 +36,7 @@
  'netmiko.ericsson',
  'netmiko.extreme',
  'netmiko.f5',
+ 'netmiko.fiberstore',
  'netmiko.flexvnf',
  'netmiko.fortinet',
  'netmiko.hillstone',
@@ -44,6 +46,7 @@
  'netmiko.juniper',
  'netmiko.keymile',
  'netmiko.linux',
+ 'netmiko.maipu',
  'netmiko.mellanox',
  'netmiko.mikrotik',
  'netmiko.mrv',
@@ -90,9 +93,9 @@
 
 setup_kwargs = {
     'name': 'netmiko',
-    'version': '4.2.0',
+    'version': '4.3.0',
     'description': 'Multi-vendor library to simplify legacy CLI connections to 
network devices',
-    'long_description': '[![PyPI - Python 
Version](https://img.shields.io/pypi/pyversions/netmiko.svg)](https://img.shields.io/pypi/pyversions/netmiko)\n[![PyPI](https://img.shields.io/pypi/v/netmiko.svg)](https://pypi.python.org/pypi/netmiko)\n[![Downloads](https://pepy.tech/badge/netmiko)](https://pepy.tech/project/netmiko)\n[![GitHub
 
contributors](https://img.shields.io/github/contributors/ktbyers/netmiko.svg)](https://GitHub.com/ktbyers/netmiko/graphs/contributors/)\n[![Code
 
Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)\n\n<img
 src="https://ktbyers.github.io/netmiko/images/netmiko_logo_gh.png"; 
width="320">\n\nNetmiko\n=======\n\nMulti-vendor library to simplify CLI 
connections to network devices\n\n<br />\n\n## Why Netmiko?\nNetwork automation 
to screen-scraping devices is primarily concerned with gathering output from 
show commands and with making configuration changes.\n\nNetmiko aims to 
accomplish both of these operations a
 nd to do it across a very broad set of platforms. It seeks to do this while 
abstracting away low-level state control (i.e. eliminate low-level regex 
pattern matching to the extent practical).\n\n<br />\n\n## Getting Started\n- 
[Getting Started](#getting-started-1)\n\n<br />\n\n## Examples\n*You really 
should look here.*\n\n- [Netmiko 
Examples](https://github.com/ktbyers/netmiko/blob/develop/EXAMPLES.md)\n\n<br 
/>\n\n\n## Supported Platforms\n\n[PLATFORMS](PLATFORMS.md)\n\n<br />\n\n\n## 
Installation\n\nTo install netmiko, simply us pip:\n\n```\n$ pip install 
netmiko\n```\n\n<br />\n\n## 
API-Documentation\n\n[API-Documentation](https://ktbyers.github.io/netmiko/docs/netmiko/index.html)\n\n<br
 />\n\n## Common Issues/FAQ\n\nAnswers to some [common 
questions](COMMON_ISSUES.md)\n\n<br />\n\n### Tutorials\n\n- [Netmiko 
Overview](https://pynet.twb-tech.com/blog/automation/netmiko.html)\n- [Secure 
Copy](https://pynet.twb-tech.com/blog/automation/netmiko-scp.html)\n- [Netmiko 
through SSH Pro
 xy](https://pynet.twb-tech.com/blog/automation/netmiko-proxy.html)\n- [Netmiko 
and 
TextFSM](https://pynet.twb-tech.com/blog/automation/netmiko-textfsm.html)\n- 
[Netmiko and what constitutes 
done](https://pynet.twb-tech.com/blog/automation/netmiko-what-is-done.html)\n\n<br
 />\n\n### Getting Started:\n\n#### Create a dictionary representing the 
device.\n\nSupported device_types can be found in 
[ssh_dispatcher.py](https://github.com/ktbyers/netmiko/blob/master/netmiko/ssh_dispatcher.py),
 see CLASS_MAPPER keys.\n```py\nfrom netmiko import ConnectHandler\n\ncisco_881 
= {\n    \'device_type\': \'cisco_ios\',\n    \'host\':   \'10.10.10.10\',\n    
\'username\': \'test\',\n    \'password\': \'password\',\n    \'port\' : 8022,  
        # optional, defaults to 22\n    \'secret\': \'secret\',     # optional, 
defaults to \'\'\n}\n\n```\n\n#### Establish an SSH connection to the device by 
passing in the device dictionary.\n\n```py\nnet_connect = 
ConnectHandler(**cisco_881)\n```\n\n#### Execute s
 how commands.\n\n```py\noutput = net_connect.send_command(\'show ip int 
brief\')\nprint(output)\n```\n```\nInterface                  IP-Address      
OK? Method Status                Protocol\nFastEthernet0              
unassigned      YES unset  down                  down\nFastEthernet1            
  unassigned      YES unset  down                  down\nFastEthernet2          
    unassigned      YES unset  down                  down\nFastEthernet3        
      unassigned      YES unset  down                  down\nFastEthernet4      
        10.10.10.10     YES manual up                    up\nVlan1              
        unassigned      YES unset  down                  down\n```\n\n#### 
Execute configuration change commands (will automatically enter into config 
mode)\n\n```py\nconfig_commands = [ \'logging buffered 20000\',\n               
     \'logging buffered 20010\',\n                    \'no logging console\' 
]\noutput = net_connect.send_config_set(config_commands)\nprint(outpu
 t)\n```\n```\npynet-rtr1#config term\nEnter configuration commands, one per 
line.  End with CNTL/Z.\npynet-rtr1(config)#logging buffered 
20000\npynet-rtr1(config)#logging buffered 20010\npynet-rtr1(config)#no logging 
console\npynet-rtr1(config)#end\npynet-rtr1#\n```\n\n<br />\n\n## 
API-Documentation\n\n<a 
href="https://ktbyers.github.io/netmiko/docs/netmiko/index.html"; 
title="Docs">API Documentation</a>\n\nBelow are some of the particularly handy 
Classes/functions for easy reference:\n- [Base Connection 
Object](https://ktbyers.github.io/netmiko/docs/netmiko/base_connection.html)\n- 
[SSH 
Autodetect](https://ktbyers.github.io/netmiko/docs/netmiko/index.html#netmiko.SSHDetect)\n-
 [SSH 
Dispatcher](https://ktbyers.github.io/netmiko/docs/netmiko/index.html#netmiko.ssh_dispatcher)\n-
 
[Redispatch](https://ktbyers.github.io/netmiko/docs/netmiko/index.html#netmiko.redispatch)\n\n<br
 />\n\n## Contributing\n\nContributors are welcome.\n\nYou can contribute to 
Netmiko in a variety of ways: answe
 ring questions on Slack (see below in Questions/Discussions), responding to 
issues, adding to the common issues, reporting/fixing bugs, or even adding your 
own device type.\n\nBefore contributing a new vendor/platform device type, 
remember that any code added needs to be supported in some fashion. To add a 
vendor/platform you can follow the outline [here](VENDOR.md). Once you\'ve 
worked on your first pass of your driver and have it functional, you\'ll need 
to include test data in order for it to be merged into develop, you can see the 
general flow of how to do that [here](TESTING.md).\n\nFor all code 
contributions, please ensure that you have ran `black` against the code or your 
code will fail the Travis CI build.\n\n<br />\n\n## Questions/Discussion\n\nIf 
you find an issue with Netmiko, then you can open an issue on this projects 
issue page here: 
[https://github.com/ktbyers/netmiko/issues](https://github.com/ktbyers/netmiko/issues).
 Please make sure you\'ve read through the common 
 issues and examples prior to opening an issue. Please only open issues for 
bugs, feature requests, or other topics related to development of Netmiko. If 
you simply have a question, join us on Slack...\n\nIf you have questions or 
would like to discuss Netmiko, a #netmiko channel exists in [this 
Slack](https://pynet.slack.com) workspace. To join, use [this 
invitation](https://join.slack.com/t/pynet/shared_invite/zt-km2k3upf-AkWHY4YEx3sI1R5irMmc7Q).
 Once you have entered the workspace, then you can join the #netmiko 
channel.\n\n\n---\nKirk Byers  \nPython for Network Engineers  
\nhttps://pynet.twb-tech.com  \n',
+    'long_description': '[![PyPI - Python 
Version](https://img.shields.io/pypi/pyversions/netmiko.svg)](https://img.shields.io/pypi/pyversions/netmiko)\n[![PyPI](https://img.shields.io/pypi/v/netmiko.svg)](https://pypi.python.org/pypi/netmiko)\n[![Downloads](https://static.pepy.tech/badge/netmiko)](https://static.pepy.tech/badge/netmiko)\n[![GitHub
 
contributors](https://img.shields.io/github/contributors/ktbyers/netmiko.svg)](https://GitHub.com/ktbyers/netmiko/graphs/contributors/)\n[![Code
 
Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)\n\n<img
 src="https://ktbyers.github.io/netmiko/images/netmiko_logo_gh.png"; 
width="320">\n\nNetmiko\n=======\n\nMulti-vendor library to simplify CLI 
connections to network devices\n\n<br />\n\n## Contributing to 
Netmiko\n\n[CONTRIBUTING.md](https://github.com/ktbyers/netmiko/blob/develop/CONTRIBUTING.md)\n\n<br
 />\n\n## Why Netmiko?\nNetwork automation to screen-scraping devices is 
primarily concerne
 d with gathering output from show commands and with making configuration 
changes.\n\nNetmiko aims to accomplish both of these operations and to do it 
across a very broad set of platforms. It seeks to do this while abstracting 
away low-level state control (i.e. eliminate low-level regex pattern matching 
to the extent practical).\n\n<br />\n\n## Getting Started\n- [Getting 
Started](#getting-started-1)\n\n<br />\n\n## Examples\n*You really should look 
here.*\n\n- [Netmiko 
Examples](https://github.com/ktbyers/netmiko/blob/develop/EXAMPLES.md)\n\n<br 
/>\n\n\n## Supported Platforms\n\n[PLATFORMS](PLATFORMS.md)\n\n<br />\n\n\n## 
Installation\n\nTo install netmiko, simply us pip:\n\n```\n$ pip install 
netmiko\n```\n\n<br />\n\n## 
API-Documentation\n\n[API-Documentation](https://ktbyers.github.io/netmiko/docs/netmiko/index.html)\n\n<br
 />\n\n## Common Issues/FAQ\n\nAnswers to some [common 
questions](COMMON_ISSUES.md)\n\n<br />\n\n### Tutorials\n\n- [Netmiko 
Overview](https://pynet.twb-tech.c
 om/blog/automation/netmiko.html)\n- [Secure 
Copy](https://pynet.twb-tech.com/blog/automation/netmiko-scp.html)\n- [Netmiko 
through SSH 
Proxy](https://pynet.twb-tech.com/blog/automation/netmiko-proxy.html)\n- 
[Netmiko and 
TextFSM](https://pynet.twb-tech.com/blog/automation/netmiko-textfsm.html)\n- 
[Netmiko and what constitutes 
done](https://pynet.twb-tech.com/blog/automation/netmiko-what-is-done.html)\n\n<br
 />\n\n### Getting Started:\n\n#### Create a dictionary representing the 
device.\n\nSupported device_types can be found in 
[ssh_dispatcher.py](https://github.com/ktbyers/netmiko/blob/master/netmiko/ssh_dispatcher.py),
 see CLASS_MAPPER keys.\n```py\nfrom netmiko import ConnectHandler\n\ncisco_881 
= {\n    \'device_type\': \'cisco_ios\',\n    \'host\':   \'10.10.10.10\',\n    
\'username\': \'test\',\n    \'password\': \'password\',\n    \'port\' : 8022,  
        # optional, defaults to 22\n    \'secret\': \'secret\',     # optional, 
defaults to \'\'\n}\n\n```\n\n#### Establish an SS
 H connection to the device by passing in the device 
dictionary.\n\n```py\nnet_connect = ConnectHandler(**cisco_881)\n```\n\n#### 
Execute show commands.\n\n```py\noutput = net_connect.send_command(\'show ip 
int brief\')\nprint(output)\n```\n```\nInterface                  IP-Address    
  OK? Method Status                Protocol\nFastEthernet0              
unassigned      YES unset  down                  down\nFastEthernet1            
  unassigned      YES unset  down                  down\nFastEthernet2          
    unassigned      YES unset  down                  down\nFastEthernet3        
      unassigned      YES unset  down                  down\nFastEthernet4      
        10.10.10.10     YES manual up                    up\nVlan1              
        unassigned      YES unset  down                  down\n```\n\n#### 
Execute configuration change commands (will automatically enter into config 
mode)\n\n```py\nconfig_commands = [ \'logging buffered 20000\',\n               
     \'l
 ogging buffered 20010\',\n                    \'no logging console\' ]\noutput 
= 
net_connect.send_config_set(config_commands)\nprint(output)\n```\n```\npynet-rtr1#config
 term\nEnter configuration commands, one per line.  End with 
CNTL/Z.\npynet-rtr1(config)#logging buffered 20000\npynet-rtr1(config)#logging 
buffered 20010\npynet-rtr1(config)#no logging 
console\npynet-rtr1(config)#end\npynet-rtr1#\n```\n\n<br />\n\n## 
API-Documentation\n\n<a 
href="https://ktbyers.github.io/netmiko/docs/netmiko/index.html"; 
title="Docs">API Documentation</a>\n\nBelow are some of the particularly handy 
Classes/functions for easy reference:\n- [Base Connection 
Object](https://ktbyers.github.io/netmiko/docs/netmiko/base_connection.html)\n- 
[SSH 
Autodetect](https://ktbyers.github.io/netmiko/docs/netmiko/index.html#netmiko.SSHDetect)\n-
 [SSH 
Dispatcher](https://ktbyers.github.io/netmiko/docs/netmiko/index.html#netmiko.ssh_dispatcher)\n-
 [Redispatch](https://ktbyers.github.io/netmiko/docs/netmiko/index.html#
 netmiko.redispatch)\n\n<br />\n\n## Contributing\n\nContributors are 
welcome.\n\nYou can contribute to Netmiko in a variety of ways: answering 
questions on Slack (see below in Questions/Discussions), responding to issues, 
adding to the common issues, reporting/fixing bugs, or even adding your own 
device type.\n\nBefore contributing a new vendor/platform device type, remember 
that any code added needs to be supported in some fashion. To add a 
vendor/platform you can follow the outline [here](VENDOR.md). Once you\'ve 
worked on your first pass of your driver and have it functional, you\'ll need 
to include test data in order for it to be merged into develop, you can see the 
general flow of how to do that [here](TESTING.md).\n\nFor all code 
contributions, please ensure that you have ran `black` against the code or your 
code will fail the Travis CI build.\n\n<br />\n\n## Questions/Discussion\n\nIf 
you find an issue with Netmiko, then you can open an issue on this projects 
issue page here:
  
[https://github.com/ktbyers/netmiko/issues](https://github.com/ktbyers/netmiko/issues).
 Please make sure you\'ve read through the common issues and examples prior to 
opening an issue. Please only open issues for bugs, feature requests, or other 
topics related to development of Netmiko. If you simply have a question, join 
us on Slack...\n\nIf you have questions or would like to discuss Netmiko, a 
#netmiko channel exists in [this Slack](https://pynet.slack.com) workspace. To 
join, use [this 
invitation](https://join.slack.com/t/pynet/shared_invite/zt-km2k3upf-AkWHY4YEx3sI1R5irMmc7Q).
 Once you have entered the workspace, then you can join the #netmiko 
channel.\n\n\n---\nKirk Byers  \nPython for Network Engineers  
\nhttps://pynet.twb-tech.com  \n',
     'author': 'Kirk Byers',
     'author_email': 'ktby...@twb-tech.com',
     'maintainer': 'None',
@@ -102,7 +105,7 @@
     'package_data': package_data,
     'install_requires': install_requires,
     'entry_points': entry_points,
-    'python_requires': '>=3.7,<4.0',
+    'python_requires': '>=3.8,<4.0',
 }
 
 

Reply via email to