derivepassphrase 0.1.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 (54) hide show
  1. derivepassphrase-0.1.0/.gitignore +6 -0
  2. derivepassphrase-0.1.0/LICENSE.txt +9 -0
  3. derivepassphrase-0.1.0/PKG-INFO +90 -0
  4. derivepassphrase-0.1.0/README.md +52 -0
  5. derivepassphrase-0.1.0/docs/index.md +1 -0
  6. derivepassphrase-0.1.0/docs/mkdocstrings_recommended_styles.css +30 -0
  7. derivepassphrase-0.1.0/docs/reference/coverage/.gitignore +2 -0
  8. derivepassphrase-0.1.0/docs/reference/coverage/class_index.html +364 -0
  9. derivepassphrase-0.1.0/docs/reference/coverage/coverage_html_cb_6fb7b396.js +733 -0
  10. derivepassphrase-0.1.0/docs/reference/coverage/coverage_html_cb_da166b87.js +717 -0
  11. derivepassphrase-0.1.0/docs/reference/coverage/favicon_32_cb_58284776.png +0 -0
  12. derivepassphrase-0.1.0/docs/reference/coverage/function_index.html +1613 -0
  13. derivepassphrase-0.1.0/docs/reference/coverage/index.html +218 -0
  14. derivepassphrase-0.1.0/docs/reference/coverage/keybd_closed_cb_ce680311.png +0 -0
  15. derivepassphrase-0.1.0/docs/reference/coverage/status.json +1 -0
  16. derivepassphrase-0.1.0/docs/reference/coverage/style_cb_8e611ae1.css +337 -0
  17. derivepassphrase-0.1.0/docs/reference/coverage/z_7eb649020e27b1af___init___py.html +600 -0
  18. derivepassphrase-0.1.0/docs/reference/coverage/z_7eb649020e27b1af_cli_py.html +1014 -0
  19. derivepassphrase-0.1.0/docs/reference/coverage/z_7eb649020e27b1af_types_py.html +234 -0
  20. derivepassphrase-0.1.0/docs/reference/coverage/z_a44f0ac069e85531___init___py.html +490 -0
  21. derivepassphrase-0.1.0/docs/reference/coverage/z_a44f0ac069e85531_test_derivepassphrase_cli_py.html +1021 -0
  22. derivepassphrase-0.1.0/docs/reference/coverage/z_a44f0ac069e85531_test_derivepassphrase_py.html +306 -0
  23. derivepassphrase-0.1.0/docs/reference/coverage/z_a44f0ac069e85531_test_derivepassphrase_typing_py.html +154 -0
  24. derivepassphrase-0.1.0/docs/reference/coverage/z_a44f0ac069e85531_test_derivepassphrase_vault_py.html +298 -0
  25. derivepassphrase-0.1.0/docs/reference/coverage/z_a44f0ac069e85531_test_key_signing_py.html +420 -0
  26. derivepassphrase-0.1.0/docs/reference/coverage/z_a44f0ac069e85531_test_sequin_py.html +214 -0
  27. derivepassphrase-0.1.0/docs/reference/coverage/z_a44f0ac069e85531_test_ssh_agent_client_py.html +419 -0
  28. derivepassphrase-0.1.0/docs/reference/coverage/z_a44f0ac069e85531_test_typing_py.html +150 -0
  29. derivepassphrase-0.1.0/docs/reference/coverage/z_b957d6aa5ed2479a___init___py.html +447 -0
  30. derivepassphrase-0.1.0/docs/reference/coverage/z_b957d6aa5ed2479a_types_py.html +149 -0
  31. derivepassphrase-0.1.0/docs/reference/coverage/z_e2689aec141aadc4___init___py.html +466 -0
  32. derivepassphrase-0.1.0/docs/reference/derivepassphrase.1.md +121 -0
  33. derivepassphrase-0.1.0/docs/reference/derivepassphrase.md +4 -0
  34. derivepassphrase-0.1.0/docs/reference/sequin.md +2 -0
  35. derivepassphrase-0.1.0/docs/reference/ssh_agent_client.md +4 -0
  36. derivepassphrase-0.1.0/docs/reference.md +18 -0
  37. derivepassphrase-0.1.0/mkdocs.yml +103 -0
  38. derivepassphrase-0.1.0/pyproject.toml +121 -0
  39. derivepassphrase-0.1.0/src/derivepassphrase/__init__.py +501 -0
  40. derivepassphrase-0.1.0/src/derivepassphrase/__main__.py +11 -0
  41. derivepassphrase-0.1.0/src/derivepassphrase/cli.py +915 -0
  42. derivepassphrase-0.1.0/src/derivepassphrase/py.typed +0 -0
  43. derivepassphrase-0.1.0/src/derivepassphrase/types.py +135 -0
  44. derivepassphrase-0.1.0/src/sequin/__init__.py +367 -0
  45. derivepassphrase-0.1.0/src/sequin/py.typed +0 -0
  46. derivepassphrase-0.1.0/src/ssh_agent_client/__init__.py +348 -0
  47. derivepassphrase-0.1.0/src/ssh_agent_client/py.typed +0 -0
  48. derivepassphrase-0.1.0/src/ssh_agent_client/types.py +50 -0
  49. derivepassphrase-0.1.0/tests/__init__.py +391 -0
  50. derivepassphrase-0.1.0/tests/test_derivepassphrase.py +207 -0
  51. derivepassphrase-0.1.0/tests/test_derivepassphrase_cli.py +922 -0
  52. derivepassphrase-0.1.0/tests/test_derivepassphrase_typing.py +55 -0
  53. derivepassphrase-0.1.0/tests/test_sequin.py +115 -0
  54. derivepassphrase-0.1.0/tests/test_ssh_agent_client.py +320 -0
@@ -0,0 +1,6 @@
1
+ html/
2
+ .mypy_cache/
3
+ .pytest_cache/
4
+ __pycache__/
5
+ *.swp
6
+ .coverage*
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright 2024 Marco Ricci <m@the13thletter.info>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,90 @@
1
+ Metadata-Version: 2.3
2
+ Name: derivepassphrase
3
+ Version: 0.1.0
4
+ Summary: An almost faithful Python reimplementation of James Coglan's vault.
5
+ Project-URL: Documentation, https://github.com/the-13th-letter/derivepassphrase#readme
6
+ Project-URL: Issues, https://github.com/the-13th-letter/derivepassphrase/issues
7
+ Project-URL: Source, https://github.com/the-13th-letter/derivepassphrase
8
+ Author-email: Marco Ricci <m@the13thletter.info>
9
+ License-Expression: MIT
10
+ License-File: LICENSE.txt
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: Implementation :: CPython
19
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: click>=8.1
22
+ Requires-Dist: typing-extensions
23
+ Provides-Extra: dev
24
+ Requires-Dist: black; extra == 'dev'
25
+ Requires-Dist: coverage; extra == 'dev'
26
+ Requires-Dist: hatch>=1.10; extra == 'dev'
27
+ Requires-Dist: hypothesis; extra == 'dev'
28
+ Requires-Dist: mkdocs; extra == 'dev'
29
+ Requires-Dist: mkdocs-material; extra == 'dev'
30
+ Requires-Dist: mkdocstrings[python]; extra == 'dev'
31
+ Requires-Dist: pytest>=8.1; extra == 'dev'
32
+ Provides-Extra: docs
33
+ Requires-Dist: black; extra == 'docs'
34
+ Requires-Dist: mkdocs; extra == 'docs'
35
+ Requires-Dist: mkdocs-material; extra == 'docs'
36
+ Requires-Dist: mkdocstrings[python]; extra == 'docs'
37
+ Description-Content-Type: text/markdown
38
+
39
+ # derivepassphrase
40
+
41
+ [![PyPI - Version](https://img.shields.io/pypi/v/derivepassphrase.svg)](https://pypi.org/project/derivepassphrase)
42
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/derivepassphrase.svg)](https://pypi.org/project/derivepassphrase)
43
+
44
+ An almost faithful Python reimplementation of [James Coglan's `vault`][VAULT], a deterministic password manager/generator.
45
+
46
+ Using a master passphrase or a master SSH key, derive a passphrase for a given named service, subject to length, character and character repetition constraints.
47
+ The derivation is cryptographically strong, meaning that even if a single passphrase is compromised, guessing the master passphrase or a different service's passphrase is computationally infeasible.
48
+ The derivation is also deterministic, given the same inputs, thus the resulting passphrase need not be stored explicitly.
49
+ The service name and constraints themselves also need not be kept secret; the latter are usually stored in a world-readable file.
50
+
51
+ [VAULT]: https://getvau.lt
52
+
53
+ -----
54
+
55
+ ## Installation
56
+
57
+ ### With `pip`
58
+
59
+ ```` shell-session
60
+ $ pip install derivepassphrase
61
+ ````
62
+
63
+ ### Manually
64
+
65
+ `derivepassphrase` is a pure Python package, and may be easily installed manually by placing the respective files into Python's import path.
66
+ `derivepassphrase` requires Python 3.11 or higher for its core functionality and programmatic interface, and [`click`][CLICK] 8.1 or higher for its command-line interface.
67
+
68
+ [CLICK]: https://click.palletsprojects.com/
69
+
70
+ ## Quick Usage
71
+
72
+ ```` shell-session
73
+ $ derivepassphrase -p --length 30 --upper 3 --lower 1 --number 2 --space 0 --symbol 0 my-email-account
74
+ Passphrase: This passphrase is for demonstration purposes only.
75
+ JKeet7GeBpxysOgdCEJo6UzmP8A0Ih
76
+ ````
77
+
78
+ Some time later…
79
+
80
+ ```` shell-session
81
+ $ derivepassphrase -p --length 30 --upper 3 --lower 1 --number 2 --space 0 --symbol 0 my-email-account
82
+ Passphrase: This passphrase is for demonstration purposes only.
83
+ JKeet7GeBpxysOgdCEJo6UzmP8A0Ih
84
+ ````
85
+
86
+ (The user input `This passphrase is for demonstration purposes only.` for the passphrase prompt is not actually displayed on-screen.)
87
+
88
+ ## License
89
+
90
+ `derivepassphrase` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
@@ -0,0 +1,52 @@
1
+ # derivepassphrase
2
+
3
+ [![PyPI - Version](https://img.shields.io/pypi/v/derivepassphrase.svg)](https://pypi.org/project/derivepassphrase)
4
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/derivepassphrase.svg)](https://pypi.org/project/derivepassphrase)
5
+
6
+ An almost faithful Python reimplementation of [James Coglan's `vault`][VAULT], a deterministic password manager/generator.
7
+
8
+ Using a master passphrase or a master SSH key, derive a passphrase for a given named service, subject to length, character and character repetition constraints.
9
+ The derivation is cryptographically strong, meaning that even if a single passphrase is compromised, guessing the master passphrase or a different service's passphrase is computationally infeasible.
10
+ The derivation is also deterministic, given the same inputs, thus the resulting passphrase need not be stored explicitly.
11
+ The service name and constraints themselves also need not be kept secret; the latter are usually stored in a world-readable file.
12
+
13
+ [VAULT]: https://getvau.lt
14
+
15
+ -----
16
+
17
+ ## Installation
18
+
19
+ ### With `pip`
20
+
21
+ ```` shell-session
22
+ $ pip install derivepassphrase
23
+ ````
24
+
25
+ ### Manually
26
+
27
+ `derivepassphrase` is a pure Python package, and may be easily installed manually by placing the respective files into Python's import path.
28
+ `derivepassphrase` requires Python 3.11 or higher for its core functionality and programmatic interface, and [`click`][CLICK] 8.1 or higher for its command-line interface.
29
+
30
+ [CLICK]: https://click.palletsprojects.com/
31
+
32
+ ## Quick Usage
33
+
34
+ ```` shell-session
35
+ $ derivepassphrase -p --length 30 --upper 3 --lower 1 --number 2 --space 0 --symbol 0 my-email-account
36
+ Passphrase: This passphrase is for demonstration purposes only.
37
+ JKeet7GeBpxysOgdCEJo6UzmP8A0Ih
38
+ ````
39
+
40
+ Some time later…
41
+
42
+ ```` shell-session
43
+ $ derivepassphrase -p --length 30 --upper 3 --lower 1 --number 2 --space 0 --symbol 0 my-email-account
44
+ Passphrase: This passphrase is for demonstration purposes only.
45
+ JKeet7GeBpxysOgdCEJo6UzmP8A0Ih
46
+ ````
47
+
48
+ (The user input `This passphrase is for demonstration purposes only.` for the passphrase prompt is not actually displayed on-screen.)
49
+
50
+ ## License
51
+
52
+ `derivepassphrase` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
@@ -0,0 +1 @@
1
+ ../README.md
@@ -0,0 +1,30 @@
1
+ /* Indentation. */
2
+ div.doc-contents:not(.first) {
3
+ padding-left: 25px;
4
+ border-left: .05rem solid var(--md-typeset-table-color);
5
+ }
6
+
7
+ /* Mark external links as such. */
8
+ div.doc-contents a[href^="https://"]::after,
9
+ div.doc-contents a[href^="http://"]::after,
10
+ div.doc-contents a[href^="//"]::after,
11
+ a.external::after,
12
+ a.autorefs-external::after {
13
+ /* https://primer.style/octicons/arrow-up-right-24 */
14
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18.25 15.5a.75.75 0 00.75-.75v-9a.75.75 0 00-.75-.75h-9a.75.75 0 000 1.5h7.19L6.22 16.72a.75.75 0 101.06 1.06L17.5 7.56v7.19c0 .414.336.75.75.75z"></path></svg>');
15
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18.25 15.5a.75.75 0 00.75-.75v-9a.75.75 0 00-.75-.75h-9a.75.75 0 000 1.5h7.19L6.22 16.72a.75.75 0 101.06 1.06L17.5 7.56v7.19c0 .414.336.75.75.75z"></path></svg>');
16
+ content: ' ';
17
+
18
+ display: inline-block;
19
+ vertical-align: middle;
20
+ position: relative;
21
+
22
+ height: 1em;
23
+ width: 1em;
24
+ background-color: currentColor;
25
+ }
26
+
27
+ a.external:hover::after,
28
+ a.autorefs-external:hover::after {
29
+ background-color: var(--md-accent-fg-color);
30
+ }
@@ -0,0 +1,2 @@
1
+ # Created by coverage.py
2
+ *
@@ -0,0 +1,364 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
+ <title>Coverage report</title>
6
+ <link rel="icon" sizes="32x32" href="favicon_32_cb_58284776.png">
7
+ <link rel="stylesheet" href="style_cb_8e611ae1.css" type="text/css">
8
+ <script src="coverage_html_cb_6fb7b396.js" defer></script>
9
+ </head>
10
+ <body class="indexfile">
11
+ <header>
12
+ <div class="content">
13
+ <h1>Coverage report:
14
+ <span class="pc_cov">99.754%</span>
15
+ </h1>
16
+ <aside id="help_panel_wrapper">
17
+ <input id="help_panel_state" type="checkbox">
18
+ <label for="help_panel_state">
19
+ <img id="keyboard_icon" src="keybd_closed_cb_ce680311.png" alt="Show/hide keyboard shortcuts">
20
+ </label>
21
+ <div id="help_panel">
22
+ <p class="legend">Shortcuts on this page</p>
23
+ <div class="keyhelp">
24
+ <p>
25
+ <kbd>f</kbd>
26
+ <kbd>n</kbd>
27
+ <kbd>s</kbd>
28
+ <kbd>m</kbd>
29
+ <kbd>x</kbd>
30
+ <kbd>b</kbd>
31
+ <kbd>p</kbd>
32
+ <kbd>c</kbd>
33
+ &nbsp; change column sorting
34
+ </p>
35
+ <p>
36
+ <kbd>[</kbd>
37
+ <kbd>]</kbd>
38
+ &nbsp; prev/next file
39
+ </p>
40
+ <p>
41
+ <kbd>?</kbd> &nbsp; show/hide this help
42
+ </p>
43
+ </div>
44
+ </div>
45
+ </aside>
46
+ <form id="filter_container">
47
+ <input id="filter" type="text" value="" placeholder="filter...">
48
+ <div>
49
+ <input id="hide100" type="checkbox" >
50
+ <label for="hide100">hide covered</label>
51
+ </div>
52
+ </form>
53
+ <h2>
54
+ <a class="button" href="index.html">Files</a>
55
+ <a class="button" href="function_index.html">Functions</a>
56
+ <a class="button current">Classes</a>
57
+ </h2>
58
+ <p class="text">
59
+ <a class="nav" href="https://coverage.readthedocs.io/en/7.6.0">coverage.py v7.6.0</a>,
60
+ created at 2024-07-14 11:39 +0200
61
+ </p>
62
+ </div>
63
+ </header>
64
+ <main id="index">
65
+ <table class="index" data-sortable>
66
+ <thead>
67
+ <tr class="tablehead" title="Click to sort">
68
+ <th id="file" class="name left" aria-sort="none" data-shortcut="f">File<span class="arrows"></span></th>
69
+ <th id="region" class="name left" aria-sort="none" data-default-sort-order="ascending" data-shortcut="n">class<span class="arrows"></span></th>
70
+ <th id="statements" aria-sort="none" data-default-sort-order="descending" data-shortcut="s">statements<span class="arrows"></span></th>
71
+ <th id="missing" aria-sort="none" data-default-sort-order="descending" data-shortcut="m">missing<span class="arrows"></span></th>
72
+ <th id="excluded" aria-sort="none" data-default-sort-order="descending" data-shortcut="x">excluded<span class="arrows"></span></th>
73
+ <th id="branches" aria-sort="none" data-default-sort-order="descending" data-shortcut="b">branches<span class="arrows"></span></th>
74
+ <th id="partial" aria-sort="none" data-default-sort-order="descending" data-shortcut="p">partial<span class="arrows"></span></th>
75
+ <th id="coverage" class="right" aria-sort="none" data-shortcut="c">coverage<span class="arrows"></span></th>
76
+ </tr>
77
+ </thead>
78
+ <tbody>
79
+ <tr class="region">
80
+ <td class="name left"><a href="z_7eb649020e27b1af___init___py.html#t28">src/derivepassphrase/__init__.py</a></td>
81
+ <td class="name left"><a href="z_7eb649020e27b1af___init___py.html#t28"><data value='Vault'>Vault</data></a></td>
82
+ <td>99</td>
83
+ <td>0</td>
84
+ <td>0</td>
85
+ <td>51</td>
86
+ <td>0</td>
87
+ <td class="right" data-ratio="150 150">100.000%</td>
88
+ </tr>
89
+ <tr class="region">
90
+ <td class="name left"><a href="z_7eb649020e27b1af___init___py.html">src/derivepassphrase/__init__.py</a></td>
91
+ <td class="name left"><a href="z_7eb649020e27b1af___init___py.html"><data value=''><span class='no-noun'>(no class)</span></data></a></td>
92
+ <td>35</td>
93
+ <td>0</td>
94
+ <td>0</td>
95
+ <td>0</td>
96
+ <td>0</td>
97
+ <td class="right" data-ratio="35 35">100.000%</td>
98
+ </tr>
99
+ <tr class="region">
100
+ <td class="name left"><a href="z_7eb649020e27b1af_cli_py.html#t299">src/derivepassphrase/cli.py</a></td>
101
+ <td class="name left"><a href="z_7eb649020e27b1af_cli_py.html#t299"><data value='OptionGroupOption'>OptionGroupOption</data></a></td>
102
+ <td>2</td>
103
+ <td>0</td>
104
+ <td>1</td>
105
+ <td>0</td>
106
+ <td>0</td>
107
+ <td class="right" data-ratio="2 2">100.000%</td>
108
+ </tr>
109
+ <tr class="region">
110
+ <td class="name left"><a href="z_7eb649020e27b1af_cli_py.html#t324">src/derivepassphrase/cli.py</a></td>
111
+ <td class="name left"><a href="z_7eb649020e27b1af_cli_py.html#t324"><data value='CommandWithHelpGroups'>CommandWithHelpGroups</data></a></td>
112
+ <td>24</td>
113
+ <td>0</td>
114
+ <td>0</td>
115
+ <td>16</td>
116
+ <td>0</td>
117
+ <td class="right" data-ratio="40 40">100.000%</td>
118
+ </tr>
119
+ <tr class="region">
120
+ <td class="name left"><a href="z_7eb649020e27b1af_cli_py.html">src/derivepassphrase/cli.py</a></td>
121
+ <td class="name left"><a href="z_7eb649020e27b1af_cli_py.html"><data value=''><span class='no-noun'>(no class)</span></data></a></td>
122
+ <td>317</td>
123
+ <td>0</td>
124
+ <td>10</td>
125
+ <td>161</td>
126
+ <td>0</td>
127
+ <td class="right" data-ratio="478 478">100.000%</td>
128
+ </tr>
129
+ <tr class="region">
130
+ <td class="name left"><a href="z_7eb649020e27b1af_types_py.html">src/derivepassphrase/types.py</a></td>
131
+ <td class="name left"><a href="z_7eb649020e27b1af_types_py.html"><data value=''><span class='no-noun'>(no class)</span></data></a></td>
132
+ <td>54</td>
133
+ <td>0</td>
134
+ <td>0</td>
135
+ <td>34</td>
136
+ <td>4</td>
137
+ <td class="right" data-ratio="84 88">95.455%</td>
138
+ </tr>
139
+ <tr class="region">
140
+ <td class="name left"><a href="z_e2689aec141aadc4___init___py.html#t33">src/sequin/__init__.py</a></td>
141
+ <td class="name left"><a href="z_e2689aec141aadc4___init___py.html#t33"><data value='Sequin'>Sequin</data></a></td>
142
+ <td>81</td>
143
+ <td>0</td>
144
+ <td>0</td>
145
+ <td>44</td>
146
+ <td>0</td>
147
+ <td class="right" data-ratio="125 125">100.000%</td>
148
+ </tr>
149
+ <tr class="region">
150
+ <td class="name left"><a href="z_e2689aec141aadc4___init___py.html">src/sequin/__init__.py</a></td>
151
+ <td class="name left"><a href="z_e2689aec141aadc4___init___py.html"><data value=''><span class='no-noun'>(no class)</span></data></a></td>
152
+ <td>16</td>
153
+ <td>0</td>
154
+ <td>0</td>
155
+ <td>0</td>
156
+ <td>0</td>
157
+ <td class="right" data-ratio="16 16">100.000%</td>
158
+ </tr>
159
+ <tr class="region">
160
+ <td class="name left"><a href="z_b957d6aa5ed2479a___init___py.html#t28">src/ssh_agent_client/__init__.py</a></td>
161
+ <td class="name left"><a href="z_b957d6aa5ed2479a___init___py.html#t28"><data value='SSHAgentClient'>SSHAgentClient</data></a></td>
162
+ <td>82</td>
163
+ <td>0</td>
164
+ <td>2</td>
165
+ <td>32</td>
166
+ <td>0</td>
167
+ <td class="right" data-ratio="114 114">100.000%</td>
168
+ </tr>
169
+ <tr class="region">
170
+ <td class="name left"><a href="z_b957d6aa5ed2479a___init___py.html">src/ssh_agent_client/__init__.py</a></td>
171
+ <td class="name left"><a href="z_b957d6aa5ed2479a___init___py.html"><data value=''><span class='no-noun'>(no class)</span></data></a></td>
172
+ <td>29</td>
173
+ <td>0</td>
174
+ <td>0</td>
175
+ <td>0</td>
176
+ <td>0</td>
177
+ <td class="right" data-ratio="29 29">100.000%</td>
178
+ </tr>
179
+ <tr class="region">
180
+ <td class="name left"><a href="z_b957d6aa5ed2479a_types_py.html">src/ssh_agent_client/types.py</a></td>
181
+ <td class="name left"><a href="z_b957d6aa5ed2479a_types_py.html"><data value=''><span class='no-noun'>(no class)</span></data></a></td>
182
+ <td>13</td>
183
+ <td>0</td>
184
+ <td>0</td>
185
+ <td>0</td>
186
+ <td>0</td>
187
+ <td class="right" data-ratio="13 13">100.000%</td>
188
+ </tr>
189
+ <tr class="region">
190
+ <td class="name left"><a href="z_a44f0ac069e85531___init___py.html">tests/__init__.py</a></td>
191
+ <td class="name left"><a href="z_a44f0ac069e85531___init___py.html"><data value=''><span class='no-noun'>(no class)</span></data></a></td>
192
+ <td>58</td>
193
+ <td>0</td>
194
+ <td>8</td>
195
+ <td>10</td>
196
+ <td>0</td>
197
+ <td class="right" data-ratio="68 68">100.000%</td>
198
+ </tr>
199
+ <tr class="region">
200
+ <td class="name left"><a href="z_a44f0ac069e85531_test_derivepassphrase_py.html#t17">tests/test_derivepassphrase.py</a></td>
201
+ <td class="name left"><a href="z_a44f0ac069e85531_test_derivepassphrase_py.html#t17"><data value='TestVault'>TestVault</data></a></td>
202
+ <td>56</td>
203
+ <td>0</td>
204
+ <td>0</td>
205
+ <td>24</td>
206
+ <td>0</td>
207
+ <td class="right" data-ratio="80 80">100.000%</td>
208
+ </tr>
209
+ <tr class="region">
210
+ <td class="name left"><a href="z_a44f0ac069e85531_test_derivepassphrase_py.html">tests/test_derivepassphrase.py</a></td>
211
+ <td class="name left"><a href="z_a44f0ac069e85531_test_derivepassphrase_py.html"><data value=''><span class='no-noun'>(no class)</span></data></a></td>
212
+ <td>37</td>
213
+ <td>0</td>
214
+ <td>0</td>
215
+ <td>0</td>
216
+ <td>0</td>
217
+ <td class="right" data-ratio="37 37">100.000%</td>
218
+ </tr>
219
+ <tr class="region">
220
+ <td class="name left"><a href="z_a44f0ac069e85531_test_derivepassphrase_cli_py.html#t153">tests/test_derivepassphrase_cli.py</a></td>
221
+ <td class="name left"><a href="z_a44f0ac069e85531_test_derivepassphrase_cli_py.html#t153"><data value='TestCLI'>TestCLI</data></a></td>
222
+ <td>190</td>
223
+ <td>0</td>
224
+ <td>4</td>
225
+ <td>68</td>
226
+ <td>0</td>
227
+ <td class="right" data-ratio="258 258">100.000%</td>
228
+ </tr>
229
+ <tr class="region">
230
+ <td class="name left"><a href="z_a44f0ac069e85531_test_derivepassphrase_cli_py.html#t713">tests/test_derivepassphrase_cli.py</a></td>
231
+ <td class="name left"><a href="z_a44f0ac069e85531_test_derivepassphrase_cli_py.html#t713"><data value='TestCLIUtils'>TestCLIUtils</data></a></td>
232
+ <td>65</td>
233
+ <td>0</td>
234
+ <td>4</td>
235
+ <td>16</td>
236
+ <td>1</td>
237
+ <td class="right" data-ratio="80 81">98.765%</td>
238
+ </tr>
239
+ <tr class="region">
240
+ <td class="name left"><a href="z_a44f0ac069e85531_test_derivepassphrase_cli_py.html">tests/test_derivepassphrase_cli.py</a></td>
241
+ <td class="name left"><a href="z_a44f0ac069e85531_test_derivepassphrase_cli_py.html"><data value=''><span class='no-noun'>(no class)</span></data></a></td>
242
+ <td>101</td>
243
+ <td>0</td>
244
+ <td>0</td>
245
+ <td>10</td>
246
+ <td>0</td>
247
+ <td class="right" data-ratio="111 111">100.000%</td>
248
+ </tr>
249
+ <tr class="region">
250
+ <td class="name left"><a href="z_a44f0ac069e85531_test_derivepassphrase_typing_py.html">tests/test_derivepassphrase_typing.py</a></td>
251
+ <td class="name left"><a href="z_a44f0ac069e85531_test_derivepassphrase_typing_py.html"><data value=''><span class='no-noun'>(no class)</span></data></a></td>
252
+ <td>8</td>
253
+ <td>0</td>
254
+ <td>0</td>
255
+ <td>0</td>
256
+ <td>0</td>
257
+ <td class="right" data-ratio="8 8">100.000%</td>
258
+ </tr>
259
+ <tr class="region">
260
+ <td class="name left"><a href="z_a44f0ac069e85531_test_sequin_py.html#t12">tests/test_sequin.py</a></td>
261
+ <td class="name left"><a href="z_a44f0ac069e85531_test_sequin_py.html#t12"><data value='TestStaticFunctionality'>TestStaticFunctionality</data></a></td>
262
+ <td>3</td>
263
+ <td>0</td>
264
+ <td>0</td>
265
+ <td>2</td>
266
+ <td>0</td>
267
+ <td class="right" data-ratio="5 5">100.000%</td>
268
+ </tr>
269
+ <tr class="region">
270
+ <td class="name left"><a href="z_a44f0ac069e85531_test_sequin_py.html#t38">tests/test_sequin.py</a></td>
271
+ <td class="name left"><a href="z_a44f0ac069e85531_test_sequin_py.html#t38"><data value='TestSequin'>TestSequin</data></a></td>
272
+ <td>37</td>
273
+ <td>0</td>
274
+ <td>0</td>
275
+ <td>12</td>
276
+ <td>0</td>
277
+ <td class="right" data-ratio="49 49">100.000%</td>
278
+ </tr>
279
+ <tr class="region">
280
+ <td class="name left"><a href="z_a44f0ac069e85531_test_sequin_py.html">tests/test_sequin.py</a></td>
281
+ <td class="name left"><a href="z_a44f0ac069e85531_test_sequin_py.html"><data value=''><span class='no-noun'>(no class)</span></data></a></td>
282
+ <td>16</td>
283
+ <td>0</td>
284
+ <td>0</td>
285
+ <td>0</td>
286
+ <td>0</td>
287
+ <td class="right" data-ratio="16 16">100.000%</td>
288
+ </tr>
289
+ <tr class="region">
290
+ <td class="name left"><a href="z_a44f0ac069e85531_test_ssh_agent_client_py.html#t24">tests/test_ssh_agent_client.py</a></td>
291
+ <td class="name left"><a href="z_a44f0ac069e85531_test_ssh_agent_client_py.html#t24"><data value='TestStaticFunctionality'>TestStaticFunctionality</data></a></td>
292
+ <td>28</td>
293
+ <td>0</td>
294
+ <td>0</td>
295
+ <td>16</td>
296
+ <td>0</td>
297
+ <td class="right" data-ratio="44 44">100.000%</td>
298
+ </tr>
299
+ <tr class="region">
300
+ <td class="name left"><a href="z_a44f0ac069e85531_test_ssh_agent_client_py.html#t120">tests/test_ssh_agent_client.py</a></td>
301
+ <td class="name left"><a href="z_a44f0ac069e85531_test_ssh_agent_client_py.html#t120"><data value='TestAgentInteraction'>TestAgentInteraction</data></a></td>
302
+ <td>86</td>
303
+ <td>0</td>
304
+ <td>10</td>
305
+ <td>40</td>
306
+ <td>0</td>
307
+ <td class="right" data-ratio="126 126">100.000%</td>
308
+ </tr>
309
+ <tr class="region">
310
+ <td class="name left"><a href="z_a44f0ac069e85531_test_ssh_agent_client_py.html#t259">tests/test_ssh_agent_client.py</a></td>
311
+ <td class="name left"><a href="z_a44f0ac069e85531_test_ssh_agent_client_py.html#t259"><data value='PseudoSocket'>TestAgentInteraction.test_310_truncated_server_response.PseudoSocket</data></a></td>
312
+ <td>2</td>
313
+ <td>0</td>
314
+ <td>0</td>
315
+ <td>0</td>
316
+ <td>0</td>
317
+ <td class="right" data-ratio="2 2">100.000%</td>
318
+ </tr>
319
+ <tr class="region">
320
+ <td class="name left"><a href="z_a44f0ac069e85531_test_ssh_agent_client_py.html">tests/test_ssh_agent_client.py</a></td>
321
+ <td class="name left"><a href="z_a44f0ac069e85531_test_ssh_agent_client_py.html"><data value=''><span class='no-noun'>(no class)</span></data></a></td>
322
+ <td>50</td>
323
+ <td>0</td>
324
+ <td>0</td>
325
+ <td>4</td>
326
+ <td>0</td>
327
+ <td class="right" data-ratio="54 54">100.000%</td>
328
+ </tr>
329
+ </tbody>
330
+ <tfoot>
331
+ <tr class="total">
332
+ <td class="name left">Total</td>
333
+ <td class="name left">&nbsp;</td>
334
+ <td>1489</td>
335
+ <td>0</td>
336
+ <td>39</td>
337
+ <td>540</td>
338
+ <td>5</td>
339
+ <td class="right" data-ratio="2024 2029">99.754%</td>
340
+ </tr>
341
+ </tfoot>
342
+ </table>
343
+ <p id="no_rows">
344
+ No items found using the specified filter.
345
+ </p>
346
+ <p>16 empty classes skipped.</p>
347
+ </main>
348
+ <footer>
349
+ <div class="content">
350
+ <p>
351
+ <a class="nav" href="https://coverage.readthedocs.io/en/7.6.0">coverage.py v7.6.0</a>,
352
+ created at 2024-07-14 11:39 +0200
353
+ </p>
354
+ </div>
355
+ <aside class="hidden">
356
+ <a id="prevFileLink" class="nav" href=""></a>
357
+ <a id="nextFileLink" class="nav" href=""></a>
358
+ <button type="button" class="button_prev_file" data-shortcut="["></button>
359
+ <button type="button" class="button_next_file" data-shortcut="]"></button>
360
+ <button type="button" class="button_show_hide_help" data-shortcut="?"></button>
361
+ </aside>
362
+ </footer>
363
+ </body>
364
+ </html>