scrapli2 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. scrapli2-2.0.0/LICENSE +21 -0
  2. scrapli2-2.0.0/MANIFEST.in +5 -0
  3. scrapli2-2.0.0/PKG-INFO +59 -0
  4. scrapli2-2.0.0/README.md +11 -0
  5. scrapli2-2.0.0/pyproject.toml +115 -0
  6. scrapli2-2.0.0/requirements-dev.txt +8 -0
  7. scrapli2-2.0.0/requirements-docs.txt +5 -0
  8. scrapli2-2.0.0/requirements-genie.txt +2 -0
  9. scrapli2-2.0.0/requirements-textfsm.txt +2 -0
  10. scrapli2-2.0.0/requirements.txt +0 -0
  11. scrapli2-2.0.0/scrapli/__init__.py +33 -0
  12. scrapli2-2.0.0/scrapli/auth.py +237 -0
  13. scrapli2-2.0.0/scrapli/cli.py +2202 -0
  14. scrapli2-2.0.0/scrapli/cli_decorators.py +148 -0
  15. scrapli2-2.0.0/scrapli/cli_parse.py +161 -0
  16. scrapli2-2.0.0/scrapli/cli_result.py +371 -0
  17. scrapli2-2.0.0/scrapli/definitions/__init__.py +1 -0
  18. scrapli2-2.0.0/scrapli/definitions/aethra_atosnt.yaml +9 -0
  19. scrapli2-2.0.0/scrapli/definitions/alcatel_aos.yaml +9 -0
  20. scrapli2-2.0.0/scrapli/definitions/arista_eos.yaml +65 -0
  21. scrapli2-2.0.0/scrapli/definitions/aruba_aoscx.yaml +33 -0
  22. scrapli2-2.0.0/scrapli/definitions/aruba_wlc.yaml +62 -0
  23. scrapli2-2.0.0/scrapli/definitions/cisco_aireos.yaml +31 -0
  24. scrapli2-2.0.0/scrapli/definitions/cisco_asa.yaml +48 -0
  25. scrapli2-2.0.0/scrapli/definitions/cisco_cbs.yaml +50 -0
  26. scrapli2-2.0.0/scrapli/definitions/cisco_ftd.yaml +42 -0
  27. scrapli2-2.0.0/scrapli/definitions/cisco_iosxe.yaml +64 -0
  28. scrapli2-2.0.0/scrapli/definitions/cisco_iosxr.yaml +47 -0
  29. scrapli2-2.0.0/scrapli/definitions/cisco_nxos.yaml +67 -0
  30. scrapli2-2.0.0/scrapli/definitions/cumulus_linux.yaml +28 -0
  31. scrapli2-2.0.0/scrapli/definitions/cumulus_vtysh.yaml +42 -0
  32. scrapli2-2.0.0/scrapli/definitions/datacom_dmos.yaml +30 -0
  33. scrapli2-2.0.0/scrapli/definitions/datacom_dmswitch.yaml +32 -0
  34. scrapli2-2.0.0/scrapli/definitions/default.yaml +9 -0
  35. scrapli2-2.0.0/scrapli/definitions/dell_emc.yaml +46 -0
  36. scrapli2-2.0.0/scrapli/definitions/dell_enterprisesonic.yaml +40 -0
  37. scrapli2-2.0.0/scrapli/definitions/dlink_os.yaml +46 -0
  38. scrapli2-2.0.0/scrapli/definitions/edgecore_ecs.yaml +35 -0
  39. scrapli2-2.0.0/scrapli/definitions/eltex_esr.yaml +43 -0
  40. scrapli2-2.0.0/scrapli/definitions/fortinet_fortios.yaml +20 -0
  41. scrapli2-2.0.0/scrapli/definitions/fortinet_wlc.yaml +33 -0
  42. scrapli2-2.0.0/scrapli/definitions/hp_comware.yaml +31 -0
  43. scrapli2-2.0.0/scrapli/definitions/huawei_smartax.yaml +67 -0
  44. scrapli2-2.0.0/scrapli/definitions/huawei_vrp.yaml +56 -0
  45. scrapli2-2.0.0/scrapli/definitions/ipinfusion_ocnos.yaml +57 -0
  46. scrapli2-2.0.0/scrapli/definitions/juniper_junos.yaml +88 -0
  47. scrapli2-2.0.0/scrapli/definitions/mikrotik_routeros.yaml +9 -0
  48. scrapli2-2.0.0/scrapli/definitions/nokia_srlinux.yaml +50 -0
  49. scrapli2-2.0.0/scrapli/definitions/nokia_sros.yaml +31 -0
  50. scrapli2-2.0.0/scrapli/definitions/nokia_sros_classic.yaml +33 -0
  51. scrapli2-2.0.0/scrapli/definitions/nokia_sros_classic_aram.yaml +25 -0
  52. scrapli2-2.0.0/scrapli/definitions/paloalto_panos.yaml +36 -0
  53. scrapli2-2.0.0/scrapli/definitions/raisecom_ros.yaml +47 -0
  54. scrapli2-2.0.0/scrapli/definitions/ruckus_fastiron.yaml +45 -0
  55. scrapli2-2.0.0/scrapli/definitions/ruckus_unleashed.yaml +64 -0
  56. scrapli2-2.0.0/scrapli/definitions/ruijie_rgos.yaml +48 -0
  57. scrapli2-2.0.0/scrapli/definitions/siemens_roxii.yaml +28 -0
  58. scrapli2-2.0.0/scrapli/definitions/ubiquiti_edgeswitch.yaml +47 -0
  59. scrapli2-2.0.0/scrapli/definitions/versa_flexvnf.yaml +45 -0
  60. scrapli2-2.0.0/scrapli/definitions/vyos_vyos.yaml +35 -0
  61. scrapli2-2.0.0/scrapli/definitions/zyxel_dslam.yaml +18 -0
  62. scrapli2-2.0.0/scrapli/exceptions.py +69 -0
  63. scrapli2-2.0.0/scrapli/ffi.py +117 -0
  64. scrapli2-2.0.0/scrapli/ffi_mapping.py +507 -0
  65. scrapli2-2.0.0/scrapli/ffi_mapping_cli.py +1126 -0
  66. scrapli2-2.0.0/scrapli/ffi_mapping_netconf.py +1839 -0
  67. scrapli2-2.0.0/scrapli/ffi_options.py +342 -0
  68. scrapli2-2.0.0/scrapli/ffi_types.py +495 -0
  69. scrapli2-2.0.0/scrapli/helper.py +254 -0
  70. scrapli2-2.0.0/scrapli/lib/__init__.py +1 -0
  71. scrapli2-2.0.0/scrapli/lib/libscrapli-x86_64-linux-gnu.so.0.0.1 +0 -0
  72. scrapli2-2.0.0/scrapli/netconf.py +2910 -0
  73. scrapli2-2.0.0/scrapli/netconf_decorators.py +146 -0
  74. scrapli2-2.0.0/scrapli/netconf_result.py +166 -0
  75. scrapli2-2.0.0/scrapli/py.typed +0 -0
  76. scrapli2-2.0.0/scrapli/session.py +139 -0
  77. scrapli2-2.0.0/scrapli/transport.py +424 -0
  78. scrapli2-2.0.0/scrapli2.egg-info/PKG-INFO +59 -0
  79. scrapli2-2.0.0/scrapli2.egg-info/SOURCES.txt +82 -0
  80. scrapli2-2.0.0/scrapli2.egg-info/dependency_links.txt +1 -0
  81. scrapli2-2.0.0/scrapli2.egg-info/requires.txt +28 -0
  82. scrapli2-2.0.0/scrapli2.egg-info/top_level.txt +1 -0
  83. scrapli2-2.0.0/setup.cfg +4 -0
  84. scrapli2-2.0.0/setup.py +415 -0
scrapli2-2.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Carl Montanari
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,5 @@
1
+ include requirements*.txt
2
+ include scrapli/definitions/*.yaml
3
+ include scrapli/lib/__init__.py
4
+ include scrapli/lib/*.so.*
5
+ include scrapli/lib/*.dylib
@@ -0,0 +1,59 @@
1
+ Metadata-Version: 2.4
2
+ Name: scrapli2
3
+ Version: 2.0.0
4
+ Summary: Fast, flexible, sync/async, Python 3.10+ screen scraping client specifically for network devices
5
+ Author-email: Carl Montanari <carl.r.montanari@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Docs, https://carlmontanari.github.io/scrapli/
8
+ Project-URL: Homepage, https://github.com/carlmontanari/scrapli
9
+ Keywords: netconf,network,cli,ssh,telnet,async
10
+ Classifier: Operating System :: POSIX :: Linux
11
+ Classifier: Operating System :: MacOS
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Provides-Extra: dev
24
+ Requires-Dist: nox==2025.5.1; extra == "dev"
25
+ Requires-Dist: black<26.0.0,>=25.1.0; extra == "dev"
26
+ Requires-Dist: isort<7.0.0,>=6.0.1; extra == "dev"
27
+ Requires-Dist: ruff<1.0.0,>=0.11.8; extra == "dev"
28
+ Requires-Dist: mypy<2.0.0,>=1.15.0; extra == "dev"
29
+ Requires-Dist: pytest<9.0.0,>=8.3.5; extra == "dev"
30
+ Requires-Dist: pytest-cov<7.0.0,>=6.1.1; extra == "dev"
31
+ Requires-Dist: pytest-asyncio<1.0.0,>=0.26.0; extra == "dev"
32
+ Requires-Dist: pyats>=20.2; extra == "dev"
33
+ Requires-Dist: genie>=20.2; extra == "dev"
34
+ Requires-Dist: ntc-templates<8.0.0,>=1.1.0; extra == "dev"
35
+ Requires-Dist: textfsm<2.0.0,>=1.1.0; extra == "dev"
36
+ Provides-Extra: full
37
+ Requires-Dist: ntc-templates<8.0.0,>=1.1.0; extra == "full"
38
+ Requires-Dist: textfsm<2.0.0,>=1.1.0; extra == "full"
39
+ Requires-Dist: pyats>=20.2; extra == "full"
40
+ Requires-Dist: genie>=20.2; extra == "full"
41
+ Provides-Extra: textfsm
42
+ Requires-Dist: ntc-templates<8.0.0,>=1.1.0; extra == "textfsm"
43
+ Requires-Dist: textfsm<2.0.0,>=1.1.0; extra == "textfsm"
44
+ Provides-Extra: genie
45
+ Requires-Dist: pyats>=20.2; extra == "genie"
46
+ Requires-Dist: genie>=20.2; extra == "genie"
47
+ Dynamic: license-file
48
+
49
+ <p center><a href=""><img src=https://github.com/carlmontanari/scrapli/blob/main/scrapli.svg?sanitize=true/></a></p>
50
+
51
+ [![Supported Versions](https://img.shields.io/pypi/pyversions/scrapli.svg)](https://pypi.org/project/scrapli)
52
+ [![PyPI version](https://badge.fury.io/py/scrapli.svg)](https://badge.fury.io/py/scrapli)
53
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blueviolet.svg)](https://opensource.org/licenses/MIT)
54
+
55
+ scrapli
56
+ =======
57
+
58
+ scrapli -- scrap(e c)li -- is a python 3.10+ library focused on connecting to devices, specifically network devices
59
+ (routers/switches/firewalls/etc.) via Telnet, SSH or NETCONF.
@@ -0,0 +1,11 @@
1
+ <p center><a href=""><img src=https://github.com/carlmontanari/scrapli/blob/main/scrapli.svg?sanitize=true/></a></p>
2
+
3
+ [![Supported Versions](https://img.shields.io/pypi/pyversions/scrapli.svg)](https://pypi.org/project/scrapli)
4
+ [![PyPI version](https://badge.fury.io/py/scrapli.svg)](https://badge.fury.io/py/scrapli)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blueviolet.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ scrapli
8
+ =======
9
+
10
+ scrapli -- scrap(e c)li -- is a python 3.10+ library focused on connecting to devices, specifically network devices
11
+ (routers/switches/firewalls/etc.) via Telnet, SSH or NETCONF.
@@ -0,0 +1,115 @@
1
+ [build-system]
2
+ build-backend = "setuptools.build_meta"
3
+ requires = ["setuptools", "wheel", "ziglang==0.16.0"]
4
+
5
+ [project]
6
+ name = "scrapli2"
7
+ description = "Fast, flexible, sync/async, Python 3.10+ screen scraping client specifically for network devices"
8
+ readme = "README.md"
9
+ keywords = ["netconf", "network", "cli", "ssh", "telnet", "async"]
10
+ license = "MIT"
11
+ authors = [{ name = "Carl Montanari", email = "carl.r.montanari@gmail.com" }]
12
+ requires-python = ">=3.10"
13
+ classifiers = [
14
+ "Operating System :: POSIX :: Linux",
15
+ "Operating System :: MacOS",
16
+ "Programming Language :: Python",
17
+ "Programming Language :: Python :: 3.10",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
21
+ "Programming Language :: Python :: 3.14",
22
+ "Programming Language :: Python :: 3 :: Only",
23
+ "Topic :: Software Development :: Libraries :: Python Modules",
24
+ ]
25
+ dynamic = ["dependencies", "optional-dependencies", "version"]
26
+ [project.urls]
27
+ Docs = "https://carlmontanari.github.io/scrapli/"
28
+ Homepage = "https://github.com/carlmontanari/scrapli"
29
+
30
+ [tool.setuptools]
31
+ packages = ["scrapli", "scrapli.definitions", "scrapli.lib"]
32
+
33
+ [tool.setuptools.dynamic]
34
+ version = { attr = "scrapli.__version__" }
35
+ dependencies = { file = "requirements.txt" }
36
+ optional-dependencies.dev = { file = [
37
+ "requirements-dev.txt",
38
+ "requirements-genie.txt",
39
+ "requirements-textfsm.txt",
40
+ ] }
41
+ optional-dependencies.full = { file = [
42
+ "requirements-textfsm.txt",
43
+ "requirements-genie.txt",
44
+ ] }
45
+ optional-dependencies.textfsm = { file = "requirements-textfsm.txt" }
46
+ optional-dependencies.genie = { file = "requirements-genie.txt" }
47
+
48
+ [tool.setuptools.package-data]
49
+ scrapli = [
50
+ "py.typed",
51
+ "scrapli/definitions/*.yaml",
52
+ "scrapli/lib/*.so.*",
53
+ "scrapli/lib/*.dylib",
54
+ ]
55
+
56
+ [tool.black]
57
+ line-length = 100
58
+ target-version = ["py313"]
59
+
60
+ [tool.isort]
61
+ profile = "black"
62
+ line_length = 100
63
+ multi_line_output = 3
64
+ include_trailing_comma = true
65
+
66
+ [tool.mypy]
67
+ python_version = "3.13"
68
+ pretty = true
69
+ ignore_missing_imports = true
70
+ warn_redundant_casts = true
71
+ warn_unused_configs = true
72
+ strict_optional = true
73
+
74
+ [tool.ruff]
75
+ include = ["setup.py", "scrapli/**.py", "examples/**.py", "tests/**.py"]
76
+ line-length = 100
77
+
78
+ [tool.ruff.lint]
79
+ select = [
80
+ "FIX",
81
+ "D",
82
+ "PL",
83
+ "ERA",
84
+ "C90",
85
+ "N",
86
+ "PERF",
87
+ "E",
88
+ "W",
89
+ "D",
90
+ "F",
91
+ "UP",
92
+ "FURB",
93
+ "RUF",
94
+ ]
95
+ ignore = [
96
+ "D105", # Missing docstring in magic method
97
+ "D107", # Missing docstring in `__init__`
98
+ "D212", # Multi-line docstring summary should start at the first line
99
+ "D415", # First line should end with a period, question mark, or exclamation point
100
+ "N818", # Exception name `foo` should be named with an Error suffix
101
+ "UP015", # Unnecessary mode argument
102
+ ]
103
+
104
+ [tool.ruff.lint.pydocstyle]
105
+ convention = "google"
106
+
107
+ [tool.ruff.lint.per-file-ignores]
108
+ "scrapli/ffi_mapping_*.py" = ["PLR0913"]
109
+ "tests/**.py" = ["D", "E501", "PLR0913"]
110
+
111
+ [tool.pytest.ini_options]
112
+ asyncio_default_fixture_loop_scope = "function"
113
+ log_cli = true
114
+ log_cli_level = "CRITICAL"
115
+ log_cli_format = "%(asctime)s [%(levelname)s] %(message)s"
@@ -0,0 +1,8 @@
1
+ nox==2025.5.1
2
+ black>=25.1.0,<26.0.0
3
+ isort>=6.0.1,<7.0.0
4
+ ruff>=0.11.8,<1.0.0
5
+ mypy>=1.15.0,<2.0.0
6
+ pytest>=8.3.5,<9.0.0
7
+ pytest-cov>=6.1.1,<7.0.0
8
+ pytest-asyncio>=0.26.0,<1.0.0
@@ -0,0 +1,5 @@
1
+ mkdocs>=1.4.3,<2.0.0
2
+ mkdocs-material>=9.1.16,<10.0.0
3
+ pygments>=2.19.2,<3.0.0
4
+ pymdown-extensions>=10.16.1,<11.0.0
5
+ mkdocs-spellcheck[codespell]>=1.1.2,<2.0.0
@@ -0,0 +1,2 @@
1
+ pyats>=20.2
2
+ genie>=20.2
@@ -0,0 +1,2 @@
1
+ ntc-templates>=1.1.0,<8.0.0
2
+ textfsm>=1.1.0,<2.0.0
File without changes
@@ -0,0 +1,33 @@
1
+ """scrapli"""
2
+
3
+ from scrapli.auth import LookupKeyValue
4
+ from scrapli.auth import Options as AuthOptions
5
+ from scrapli.cli import Cli, ReadCallback
6
+ from scrapli.netconf import Netconf
7
+ from scrapli.netconf import Options as NetconfOptions
8
+ from scrapli.session import Options as SessionOptions
9
+ from scrapli.transport import BinOptions as TransportBinOptions
10
+ from scrapli.transport import Ssh2Options as TransportSsh2Options
11
+ from scrapli.transport import TelnetOptions as TransportTelnetOptions
12
+ from scrapli.transport import TestOptions as TransportTestOptions
13
+
14
+ # set in ci on release
15
+ __version__ = "2.0.0"
16
+ __semver_version__ = "2.0.0"
17
+ __calendar_version__ = "2026.10.03"
18
+
19
+ __definitions_version__ = "0.0.5"
20
+
21
+ __all__ = (
22
+ "AuthOptions",
23
+ "Cli",
24
+ "LookupKeyValue",
25
+ "Netconf",
26
+ "NetconfOptions",
27
+ "ReadCallback",
28
+ "SessionOptions",
29
+ "TransportBinOptions",
30
+ "TransportSsh2Options",
31
+ "TransportTelnetOptions",
32
+ "TransportTestOptions",
33
+ )
@@ -0,0 +1,237 @@
1
+ """scrapli.auth"""
2
+
3
+ from ctypes import Array, c_bool, c_char_p, c_size_t, c_uint16, pointer
4
+ from dataclasses import dataclass, field
5
+
6
+ from scrapli.ffi_options import DriverOptionsPointer
7
+ from scrapli.ffi_types import to_c_string
8
+
9
+
10
+ @dataclass
11
+ class LookupKeyValue:
12
+ """
13
+ Options a "lookup" key/value pair.
14
+
15
+ Used in conjuection with platform definition templating like `__lookup::enable` where "enable"
16
+ is the key to "lookup" in the list of lookup key/values.
17
+
18
+ Args:
19
+ key: the name of the lookup key
20
+ value: the value of the lookup key
21
+
22
+ Returns:
23
+ None
24
+
25
+ Raises:
26
+ N/A
27
+
28
+ """
29
+
30
+ key: str
31
+ value: str
32
+
33
+ _key: c_char_p | None = field(init=False, default=None, repr=False)
34
+ _value: c_char_p | None = field(init=False, default=None, repr=False)
35
+
36
+ def _get_c_strings(self) -> tuple[c_char_p, c_char_p]:
37
+ self._key = to_c_string(self.key)
38
+ self._value = to_c_string(self.value)
39
+
40
+ return self._key, self._value
41
+
42
+ def __repr__(self) -> str:
43
+ return f"{self.__class__.__name__}(key='{self.key}', value='REDACTED')"
44
+
45
+
46
+ @dataclass
47
+ class Options:
48
+ """
49
+ Options holds auth related options to pass to the ffi layer.
50
+
51
+ All arguments are optional, though you will almost certainly need to provide *some* -- for
52
+ example a username and password or key.
53
+
54
+ Args:
55
+ username: the username to use for the connection
56
+ password: the password to use for the connection
57
+ private_key_path: filepath to the ssh private key to use
58
+ private_key_passphrase: the private key passphrase if set
59
+ private_key_content: the private key content to use -- only supported w/ ssh2 transport.
60
+ lookups: a list of key/values that can be "looked up" from a connection -- used in
61
+ conjunction with platform definition templating like `__lookup::enable` where "enable"
62
+ is the key to "lookup" in the list of lookup key/values.
63
+ force_in_session_auth: unconditionally force the in session auth process.
64
+ bypass_in_session_auth: skip in session auth even if transport (telnet/bin) expect it.
65
+ username_pattern: the regex pattern to use to look for a username prompt
66
+ password_pattern: the regex pattern to use to look for a password prompt
67
+ private_key_passphrase_pattern: the regex pattern to use to look for a passphrase prompt
68
+
69
+ Returns:
70
+ None
71
+
72
+ Raises:
73
+ N/A
74
+
75
+ """
76
+
77
+ username: str | None = None
78
+ password: str | None = None
79
+ private_key_path: str | None = None
80
+ private_key_passphrase: str | None = None
81
+ private_key_content: str | None = None
82
+ lookups: list[LookupKeyValue] | None = None
83
+ force_in_session_auth: bool | None = None
84
+ bypass_in_session_auth: bool | None = None
85
+ username_pattern: str | None = None
86
+ password_pattern: str | None = None
87
+ private_key_passphrase_pattern: str | None = None
88
+
89
+ _username: c_char_p | None = field(init=False, default=None, repr=False)
90
+ _password: c_char_p | None = field(init=False, default=None, repr=False)
91
+ _private_key_path: c_char_p | None = field(init=False, default=None, repr=False)
92
+ _private_key_passphrase: c_char_p | None = field(init=False, default=None, repr=False)
93
+ _private_key_content: c_char_p | None = field(init=False, default=None, repr=False)
94
+ _username_pattern: c_char_p | None = field(init=False, default=None, repr=False)
95
+ _password_pattern: c_char_p | None = field(init=False, default=None, repr=False)
96
+ _private_key_passphrase_pattern: c_char_p | None = field(init=False, default=None, repr=False)
97
+
98
+ _lookup_map_keys: Array[c_char_p] | None = field(init=False, default=None, repr=False)
99
+ _lookup_map_key_lens: Array[c_uint16] | None = field(init=False, default=None, repr=False)
100
+ _lookup_map_vals: Array[c_char_p] | None = field(init=False, default=None, repr=False)
101
+ _lookup_map_val_lens: Array[c_uint16] | None = field(init=False, default=None, repr=False)
102
+
103
+ def apply(self, *, options: DriverOptionsPointer) -> None: # noqa: C901,PLR0915
104
+ """
105
+ Applies the options to the given options struct.
106
+
107
+ Should not be called directly/by users.
108
+
109
+ Args:
110
+ options: the options struct to write set options to
111
+
112
+ Returns:
113
+ None
114
+
115
+ Raises:
116
+ N/A
117
+
118
+ """
119
+ if self.username is not None:
120
+ self._username = to_c_string(self.username)
121
+
122
+ options.contents.auth.username = self._username
123
+ options.contents.auth.username_len = c_size_t(len(self.username))
124
+
125
+ if self.password is not None:
126
+ self._password = to_c_string(self.password)
127
+
128
+ options.contents.auth.password = self._password
129
+ options.contents.auth.password_len = c_size_t(len(self.password))
130
+
131
+ if self.private_key_path is not None:
132
+ self._private_key_path = to_c_string(self.private_key_path)
133
+
134
+ options.contents.auth.private_key_path = self._private_key_path
135
+ options.contents.auth.private_key_path_len = c_size_t(len(self.private_key_path))
136
+
137
+ if self.private_key_passphrase is not None:
138
+ self._private_key_passphrase = to_c_string(self.private_key_passphrase)
139
+
140
+ options.contents.auth.private_key_passphrase = self._private_key_passphrase
141
+ options.contents.auth.private_key_passphrase_len = c_size_t(
142
+ len(self.private_key_passphrase)
143
+ )
144
+
145
+ if self.private_key_content is not None:
146
+ self._private_key_content = to_c_string(self.private_key_content)
147
+
148
+ options.contents.auth.private_key_content = self._private_key_content
149
+ options.contents.auth.private_key_content_len = c_size_t(len(self.private_key_content))
150
+
151
+ if self.lookups is not None:
152
+ count = len(self.lookups)
153
+
154
+ self._lookup_map_keys = (c_char_p * count)()
155
+ self._lookup_map_key_lens = (c_uint16 * count)()
156
+ self._lookup_map_vals = (c_char_p * count)()
157
+ self._lookup_map_val_lens = (c_uint16 * count)()
158
+
159
+ for i, lookup in enumerate(self.lookups):
160
+ k, v = lookup._get_c_strings()
161
+
162
+ self._lookup_map_keys[i] = k
163
+ self._lookup_map_key_lens[i] = c_uint16(len(lookup.key))
164
+
165
+ self._lookup_map_vals[i] = v
166
+ self._lookup_map_val_lens[i] = c_uint16(len(lookup.value))
167
+
168
+ options.contents.auth.lookups.keys = self._lookup_map_keys
169
+ options.contents.auth.lookups.key_lens = self._lookup_map_key_lens
170
+
171
+ options.contents.auth.lookups.vals = self._lookup_map_vals
172
+ options.contents.auth.lookups.val_lens = self._lookup_map_val_lens
173
+
174
+ options.contents.auth.lookups.count = c_size_t(len(self.lookups))
175
+
176
+ if self.force_in_session_auth is not None:
177
+ options.contents.auth.force_in_session_auth = pointer(
178
+ c_bool(self.force_in_session_auth)
179
+ )
180
+
181
+ if self.bypass_in_session_auth is not None:
182
+ options.contents.auth.bypass_in_session_auth = pointer(
183
+ c_bool(self.bypass_in_session_auth)
184
+ )
185
+
186
+ if self.username_pattern is not None:
187
+ self._username_pattern = to_c_string(self.username_pattern)
188
+
189
+ options.contents.auth.username_pattern = self._username_pattern
190
+ options.contents.auth.username_pattern_len = c_size_t(len(self.username_pattern))
191
+
192
+ if self.password_pattern is not None:
193
+ self._password_pattern = to_c_string(self.password_pattern)
194
+
195
+ options.contents.auth.password_pattern = self._password_pattern
196
+ options.contents.auth.password_pattern_len = c_size_t(len(self.password_pattern))
197
+
198
+ if self.private_key_passphrase_pattern is not None:
199
+ self._private_key_passphrase_pattern = to_c_string(self.private_key_passphrase_pattern)
200
+
201
+ options.contents.auth.private_key_passphrase_pattern = (
202
+ self._private_key_passphrase_pattern
203
+ )
204
+ options.contents.auth.private_key_passphrase_pattern_len = c_size_t(
205
+ len(self.private_key_passphrase_pattern)
206
+ )
207
+
208
+ def __repr__(self) -> str:
209
+ """
210
+ Magic repr method for Options object
211
+
212
+ Args:
213
+ N/A
214
+
215
+ Returns:
216
+ str: repr for Options object
217
+
218
+ Raises:
219
+ N/A
220
+
221
+ """
222
+ return (
223
+ # it will probably be "canonical" to import Options as AuthOptions, so we'll make
224
+ # the repr do that too
225
+ f"Auth{self.__class__.__name__}("
226
+ f"username={self.username!r}, "
227
+ f"password={None if not self.password else 'REDACTED'}, "
228
+ f"private_key_path={self.private_key_path!r}, "
229
+ f"private_key_passphrase={None if not self.private_key_passphrase else 'REDACTED'}, "
230
+ f"private_key_content={None if not self.private_key_content else 'REDACTED'}, "
231
+ f"lookups={self.lookups!r}, "
232
+ f"force_in_session_auth={self.force_in_session_auth!r}, "
233
+ f"bypass_in_session_auth={self.bypass_in_session_auth!r}, "
234
+ f"username_pattern={self.username_pattern!r}, "
235
+ f"password_pattern={self.password_pattern!r}, "
236
+ f"private_key_passphrase_pattern={self.private_key_passphrase_pattern!r})"
237
+ )