shvcli 0.6.1__tar.gz → 0.7.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.
- {shvcli-0.6.1/shvcli.egg-info → shvcli-0.7.0}/PKG-INFO +43 -26
- {shvcli-0.6.1 → shvcli-0.7.0}/README.rst +38 -22
- {shvcli-0.6.1 → shvcli-0.7.0}/pyproject.toml +3 -5
- shvcli-0.7.0/shvcli/__init__.py +55 -0
- shvcli-0.7.0/shvcli/__main__.py +36 -0
- shvcli-0.7.0/shvcli/afterconn.py +55 -0
- shvcli-0.7.0/shvcli/args.py +56 -0
- shvcli-0.7.0/shvcli/builtin.py +86 -0
- shvcli-0.7.0/shvcli/builtins/__init__.py +27 -0
- shvcli-0.7.0/shvcli/builtins/broker.py +100 -0
- shvcli-0.7.0/shvcli/builtins/cd.py +37 -0
- shvcli-0.7.0/shvcli/builtins/file.py +128 -0
- shvcli-0.7.0/shvcli/builtins/help.py +58 -0
- shvcli-0.7.0/shvcli/builtins/scan.py +41 -0
- shvcli-0.7.0/shvcli/builtins/set.py +70 -0
- shvcli-0.7.0/shvcli/builtins/tree.py +66 -0
- shvcli-0.7.0/shvcli/cli.py +184 -0
- shvcli-0.7.0/shvcli/client.py +133 -0
- shvcli-0.7.0/shvcli/cliitems.py +88 -0
- shvcli-0.7.0/shvcli/complet.py +86 -0
- shvcli-0.7.0/shvcli/config.py +106 -0
- shvcli-0.7.0/shvcli/file.py +68 -0
- shvcli-0.7.0/shvcli/lsdir.py +127 -0
- shvcli-0.7.0/shvcli/option.py +267 -0
- shvcli-0.7.0/shvcli/options.py +168 -0
- shvcli-0.7.0/shvcli/plugins.py +18 -0
- {shvcli-0.6.1 → shvcli-0.7.0}/shvcli/scan.py +7 -7
- shvcli-0.7.0/shvcli/state.py +96 -0
- shvcli-0.7.0/shvcli/tools/__init__.py +1 -0
- shvcli-0.7.0/shvcli/tools/complet.py +60 -0
- shvcli-0.6.1/shvcli/tools.py → shvcli-0.7.0/shvcli/tools/print.py +15 -28
- shvcli-0.7.0/shvcli/tree.py +126 -0
- shvcli-0.7.0/shvcli/url.py +110 -0
- shvcli-0.7.0/shvcli/valid.py +78 -0
- {shvcli-0.6.1 → shvcli-0.7.0/shvcli.egg-info}/PKG-INFO +43 -26
- shvcli-0.7.0/shvcli.egg-info/SOURCES.txt +42 -0
- {shvcli-0.6.1 → shvcli-0.7.0}/shvcli.egg-info/requires.txt +2 -1
- shvcli-0.6.1/shvcli/__init__.py +0 -5
- shvcli-0.6.1/shvcli/__main__.py +0 -62
- shvcli-0.6.1/shvcli/builtin.py +0 -132
- shvcli-0.6.1/shvcli/builtin_impl.py +0 -170
- shvcli-0.6.1/shvcli/cli.py +0 -136
- shvcli-0.6.1/shvcli/client.py +0 -210
- shvcli-0.6.1/shvcli/complet.py +0 -78
- shvcli-0.6.1/shvcli/complet_tools.py +0 -64
- shvcli-0.6.1/shvcli/config.py +0 -176
- shvcli-0.6.1/shvcli/lsdir.py +0 -145
- shvcli-0.6.1/shvcli/parse.py +0 -87
- shvcli-0.6.1/shvcli/valid.py +0 -41
- shvcli-0.6.1/shvcli/version +0 -1
- shvcli-0.6.1/shvcli.egg-info/SOURCES.txt +0 -26
- {shvcli-0.6.1 → shvcli-0.7.0}/LICENSE +0 -0
- {shvcli-0.6.1 → shvcli-0.7.0}/setup.cfg +0 -0
- {shvcli-0.6.1 → shvcli-0.7.0}/shvcli/__version__.py +0 -0
- {shvcli-0.6.1 → shvcli-0.7.0}/shvcli/py.typed +0 -0
- {shvcli-0.6.1 → shvcli-0.7.0}/shvcli.egg-info/dependency_links.txt +0 -0
- {shvcli-0.6.1 → shvcli-0.7.0}/shvcli.egg-info/entry_points.txt +0 -0
- {shvcli-0.6.1 → shvcli-0.7.0}/shvcli.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: shvcli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Silicon Heaven CLI access application
|
|
5
5
|
Author: Elektroline a.s.
|
|
6
6
|
License: MIT License
|
|
@@ -27,7 +27,6 @@ License: MIT License
|
|
|
27
27
|
|
|
28
28
|
Project-URL: repository, https://gitlab.com/silicon-heaven/shvcli
|
|
29
29
|
Classifier: Development Status :: 4 - Beta
|
|
30
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
31
30
|
Classifier: Programming Language :: Python :: 3
|
|
32
31
|
Classifier: Operating System :: OS Independent
|
|
33
32
|
Classifier: Environment :: Console
|
|
@@ -38,10 +37,12 @@ Classifier: Topic :: Terminals
|
|
|
38
37
|
Requires-Python: >=3.11
|
|
39
38
|
Description-Content-Type: text/x-rst
|
|
40
39
|
License-File: LICENSE
|
|
41
|
-
Requires-Dist: pyshv>=0.
|
|
40
|
+
Requires-Dist: pyshv>=0.9.0
|
|
42
41
|
Requires-Dist: prompt_toolkit
|
|
43
42
|
Requires-Dist: pygments
|
|
44
43
|
Requires-Dist: pyxdg
|
|
44
|
+
Requires-Dist: more-itertools
|
|
45
|
+
Dynamic: license-file
|
|
45
46
|
|
|
46
47
|
=====================================
|
|
47
48
|
Silicon Heaven CLI access application
|
|
@@ -101,20 +102,25 @@ An example of usage:
|
|
|
101
102
|
.app> /:
|
|
102
103
|
>
|
|
103
104
|
|
|
105
|
+
.. TIP::
|
|
106
|
+
The validation that is performed by SHVCLI is best effort and sometimes you
|
|
107
|
+
might need to submit call that is considered invalid by SHVCLI. For that
|
|
108
|
+
reason you can use `Ctrl+o` shortcut instead of pressing enter key.
|
|
109
|
+
|
|
104
110
|
|
|
105
111
|
Configuration file
|
|
106
112
|
------------------
|
|
107
113
|
|
|
108
|
-
Tool reads configuration from files ``/etc/shvcli.
|
|
109
|
-
They are in
|
|
114
|
+
Tool reads configuration from files ``/etc/shvcli.toml`` and ``~/.shvcli.toml``.
|
|
115
|
+
They are in TOML file format and the following sections are supported:
|
|
110
116
|
|
|
111
117
|
**hosts**: That provides mapping from some name to RPC URL.
|
|
112
118
|
|
|
113
119
|
**hosts-shell**: That is same as **hosts** with exception that URL is passed
|
|
114
120
|
through your local Shell to expand any variables or command substitutions.
|
|
115
121
|
|
|
116
|
-
**
|
|
117
|
-
|
|
122
|
+
**option**: That allows you to set initial setting for runtime options. The
|
|
123
|
+
following options are available without any plugins:
|
|
118
124
|
|
|
119
125
|
* **vimode**: If Vi input mode should be used for command line input. The
|
|
120
126
|
default is ``false``.
|
|
@@ -137,17 +143,15 @@ switched in runtime. The following options are available:
|
|
|
137
143
|
be also overwhelming. The default is ``false``. It is beneficial to disable
|
|
138
144
|
the **autobrobe** once you enable debug because otherwise output on CLI will
|
|
139
145
|
be mangled on completion.
|
|
140
|
-
* **
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
* **
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
* **autoget_timeout**: Timeout in seconds before call that is part of autoget
|
|
146
|
+
* **call_query_timeout**: Timeout in seconds for status request query. The
|
|
147
|
+
shorter time will result in faster request lost detection while very short
|
|
148
|
+
time will load SHV network too much.
|
|
149
|
+
* **call_retry_timeout**: Timeout in seconds when call request is sent again if
|
|
150
|
+
no response is received. This is not applied if query is and thus this mostly
|
|
151
|
+
is used only in case when method doesn't support delayed responses.
|
|
152
|
+
* **autoget_timeout**: Timeout in seconds for call that is part of autoget
|
|
148
153
|
functionality.
|
|
149
154
|
|
|
150
|
-
|
|
151
155
|
Example configuration file:
|
|
152
156
|
|
|
153
157
|
.. code-block:: ini
|
|
@@ -172,10 +176,7 @@ environment you are running in.
|
|
|
172
176
|
|
|
173
177
|
**subscribe|sub**: Add new subscribe. Shortcut to the call of
|
|
174
178
|
``.app/broker/currentClient:subscribe`` that accepts arguments in more convenient
|
|
175
|
-
way
|
|
176
|
-
same format such as method calls in this tool, that means ``PATH:METHOD`` where
|
|
177
|
-
``METHOD`` can be left out to match all methods. Pattern subscribes are not
|
|
178
|
-
supporter, yet.
|
|
179
|
+
way. The argument can be multiple RPC RIs (``PATH:METHOD:SIGNAL`` patterns).
|
|
179
180
|
|
|
180
181
|
**unsubscribe|usub**: Unsubscribe existing subscription. It is reverse operation
|
|
181
182
|
to the **subscribe** and same remarks apply here as well. It is a shortcut to
|
|
@@ -197,11 +198,20 @@ cache.
|
|
|
197
198
|
thus use it sparely.
|
|
198
199
|
|
|
199
200
|
**set|s**: allows modification of configuration option in runtime. The names
|
|
200
|
-
are the same as in ``config`` section. The boolean options
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
also
|
|
204
|
-
simply prints the current configuration.
|
|
201
|
+
are the same as in ``config`` section. The boolean options are set if no
|
|
202
|
+
argument is provided, or cleared if name is prefixed with ``no`` (and thus to
|
|
203
|
+
disable ``raw`` you use ``noraw``). You can also add ``=true`` or ``=false``.
|
|
204
|
+
The equal sign is also used with integer and floating point options. Without any
|
|
205
|
+
configuration option it simply prints the current configuration.
|
|
206
|
+
|
|
207
|
+
**upload**: provides a way to copy local file to the RPC File node. The
|
|
208
|
+
parameter must be path to the local file to be uploaded.
|
|
209
|
+
|
|
210
|
+
**download**: provides a way to copy RPC File node data to local file. The
|
|
211
|
+
parameter must be path to the local file where data will be stored.
|
|
212
|
+
|
|
213
|
+
**verify**: provides a way to verify RPC File node against local file. The
|
|
214
|
+
parameter must be path to the local file used for the verification.
|
|
205
215
|
|
|
206
216
|
|
|
207
217
|
Special methods ``ls`` and ``dir``
|
|
@@ -214,3 +224,10 @@ the fullest content.
|
|
|
214
224
|
Their parameter is also handled in a special way. It is considered to be
|
|
215
225
|
additional path suffix unless it is a valid CPON. This is allowed to match the
|
|
216
226
|
common shells.
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
Plugins
|
|
230
|
+
-------
|
|
231
|
+
|
|
232
|
+
The support for external plugins is provided. These plugins are discovered using
|
|
233
|
+
Python package metadata using the entry point ``shvcli.plugins``.
|
|
@@ -56,20 +56,25 @@ An example of usage:
|
|
|
56
56
|
.app> /:
|
|
57
57
|
>
|
|
58
58
|
|
|
59
|
+
.. TIP::
|
|
60
|
+
The validation that is performed by SHVCLI is best effort and sometimes you
|
|
61
|
+
might need to submit call that is considered invalid by SHVCLI. For that
|
|
62
|
+
reason you can use `Ctrl+o` shortcut instead of pressing enter key.
|
|
63
|
+
|
|
59
64
|
|
|
60
65
|
Configuration file
|
|
61
66
|
------------------
|
|
62
67
|
|
|
63
|
-
Tool reads configuration from files ``/etc/shvcli.
|
|
64
|
-
They are in
|
|
68
|
+
Tool reads configuration from files ``/etc/shvcli.toml`` and ``~/.shvcli.toml``.
|
|
69
|
+
They are in TOML file format and the following sections are supported:
|
|
65
70
|
|
|
66
71
|
**hosts**: That provides mapping from some name to RPC URL.
|
|
67
72
|
|
|
68
73
|
**hosts-shell**: That is same as **hosts** with exception that URL is passed
|
|
69
74
|
through your local Shell to expand any variables or command substitutions.
|
|
70
75
|
|
|
71
|
-
**
|
|
72
|
-
|
|
76
|
+
**option**: That allows you to set initial setting for runtime options. The
|
|
77
|
+
following options are available without any plugins:
|
|
73
78
|
|
|
74
79
|
* **vimode**: If Vi input mode should be used for command line input. The
|
|
75
80
|
default is ``false``.
|
|
@@ -92,17 +97,15 @@ switched in runtime. The following options are available:
|
|
|
92
97
|
be also overwhelming. The default is ``false``. It is beneficial to disable
|
|
93
98
|
the **autobrobe** once you enable debug because otherwise output on CLI will
|
|
94
99
|
be mangled on completion.
|
|
95
|
-
* **
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
* **
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
* **autoget_timeout**: Timeout in seconds before call that is part of autoget
|
|
100
|
+
* **call_query_timeout**: Timeout in seconds for status request query. The
|
|
101
|
+
shorter time will result in faster request lost detection while very short
|
|
102
|
+
time will load SHV network too much.
|
|
103
|
+
* **call_retry_timeout**: Timeout in seconds when call request is sent again if
|
|
104
|
+
no response is received. This is not applied if query is and thus this mostly
|
|
105
|
+
is used only in case when method doesn't support delayed responses.
|
|
106
|
+
* **autoget_timeout**: Timeout in seconds for call that is part of autoget
|
|
103
107
|
functionality.
|
|
104
108
|
|
|
105
|
-
|
|
106
109
|
Example configuration file:
|
|
107
110
|
|
|
108
111
|
.. code-block:: ini
|
|
@@ -127,10 +130,7 @@ environment you are running in.
|
|
|
127
130
|
|
|
128
131
|
**subscribe|sub**: Add new subscribe. Shortcut to the call of
|
|
129
132
|
``.app/broker/currentClient:subscribe`` that accepts arguments in more convenient
|
|
130
|
-
way
|
|
131
|
-
same format such as method calls in this tool, that means ``PATH:METHOD`` where
|
|
132
|
-
``METHOD`` can be left out to match all methods. Pattern subscribes are not
|
|
133
|
-
supporter, yet.
|
|
133
|
+
way. The argument can be multiple RPC RIs (``PATH:METHOD:SIGNAL`` patterns).
|
|
134
134
|
|
|
135
135
|
**unsubscribe|usub**: Unsubscribe existing subscription. It is reverse operation
|
|
136
136
|
to the **subscribe** and same remarks apply here as well. It is a shortcut to
|
|
@@ -152,11 +152,20 @@ cache.
|
|
|
152
152
|
thus use it sparely.
|
|
153
153
|
|
|
154
154
|
**set|s**: allows modification of configuration option in runtime. The names
|
|
155
|
-
are the same as in ``config`` section. The boolean options
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
also
|
|
159
|
-
simply prints the current configuration.
|
|
155
|
+
are the same as in ``config`` section. The boolean options are set if no
|
|
156
|
+
argument is provided, or cleared if name is prefixed with ``no`` (and thus to
|
|
157
|
+
disable ``raw`` you use ``noraw``). You can also add ``=true`` or ``=false``.
|
|
158
|
+
The equal sign is also used with integer and floating point options. Without any
|
|
159
|
+
configuration option it simply prints the current configuration.
|
|
160
|
+
|
|
161
|
+
**upload**: provides a way to copy local file to the RPC File node. The
|
|
162
|
+
parameter must be path to the local file to be uploaded.
|
|
163
|
+
|
|
164
|
+
**download**: provides a way to copy RPC File node data to local file. The
|
|
165
|
+
parameter must be path to the local file where data will be stored.
|
|
166
|
+
|
|
167
|
+
**verify**: provides a way to verify RPC File node against local file. The
|
|
168
|
+
parameter must be path to the local file used for the verification.
|
|
160
169
|
|
|
161
170
|
|
|
162
171
|
Special methods ``ls`` and ``dir``
|
|
@@ -169,3 +178,10 @@ the fullest content.
|
|
|
169
178
|
Their parameter is also handled in a special way. It is considered to be
|
|
170
179
|
additional path suffix unless it is a valid CPON. This is allowed to match the
|
|
171
180
|
common shells.
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
Plugins
|
|
184
|
+
-------
|
|
185
|
+
|
|
186
|
+
The support for external plugins is provided. These plugins are discovered using
|
|
187
|
+
Python package metadata using the entry point ``shvcli.plugins``.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "shvcli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.7.0"
|
|
4
4
|
description = "Silicon Heaven CLI access application"
|
|
5
5
|
readme = "README.rst"
|
|
6
6
|
license = {file = "LICENSE"}
|
|
@@ -9,7 +9,6 @@ authors = [
|
|
|
9
9
|
]
|
|
10
10
|
classifiers = [
|
|
11
11
|
"Development Status :: 4 - Beta",
|
|
12
|
-
"License :: OSI Approved :: MIT License",
|
|
13
12
|
"Programming Language :: Python :: 3",
|
|
14
13
|
"Operating System :: OS Independent",
|
|
15
14
|
"Environment :: Console",
|
|
@@ -20,10 +19,11 @@ classifiers = [
|
|
|
20
19
|
]
|
|
21
20
|
requires-python = ">=3.11"
|
|
22
21
|
dependencies = [
|
|
23
|
-
"pyshv >= 0.
|
|
22
|
+
"pyshv >= 0.9.0",
|
|
24
23
|
"prompt_toolkit",
|
|
25
24
|
"pygments",
|
|
26
25
|
"pyxdg",
|
|
26
|
+
"more-itertools",
|
|
27
27
|
]
|
|
28
28
|
|
|
29
29
|
[project.urls]
|
|
@@ -77,8 +77,6 @@ ignore = [
|
|
|
77
77
|
"PLR0916",
|
|
78
78
|
# This seems like a wrong rule
|
|
79
79
|
"PLW1641",
|
|
80
|
-
# Deprecated
|
|
81
|
-
"ANN101", "ANN102",
|
|
82
80
|
]
|
|
83
81
|
preview = true
|
|
84
82
|
[tool.ruff.lint.per-file-ignores]
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Silicon Heaven Command Line Interface."""
|
|
2
|
+
|
|
3
|
+
import importlib
|
|
4
|
+
|
|
5
|
+
from .__version__ import VERSION
|
|
6
|
+
from .args import register_argparser
|
|
7
|
+
from .builtin import Builtin, Builtins
|
|
8
|
+
from .client import Client
|
|
9
|
+
from .cliitems import CliItems
|
|
10
|
+
from .config import Config, ConfigError, register_config
|
|
11
|
+
from .option import BoolOption, FloatOption, IntOption, Option
|
|
12
|
+
from .options import (
|
|
13
|
+
AutoGetOption,
|
|
14
|
+
AutoGetTimeoutOption,
|
|
15
|
+
AutoProbeOption,
|
|
16
|
+
CallDuration,
|
|
17
|
+
CallQueryTimeout,
|
|
18
|
+
CallRetryTimeout,
|
|
19
|
+
DebugOption,
|
|
20
|
+
RawOption,
|
|
21
|
+
ViModeOption,
|
|
22
|
+
)
|
|
23
|
+
from .state import State, StateVar
|
|
24
|
+
from .tree import Node, Tree
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"VERSION",
|
|
28
|
+
"AutoGetOption",
|
|
29
|
+
"AutoGetTimeoutOption",
|
|
30
|
+
"AutoProbeOption",
|
|
31
|
+
"BoolOption",
|
|
32
|
+
"Builtin",
|
|
33
|
+
"Builtins",
|
|
34
|
+
"CallDuration",
|
|
35
|
+
"CallQueryTimeout",
|
|
36
|
+
"CallRetryTimeout",
|
|
37
|
+
"CliItems",
|
|
38
|
+
"Client",
|
|
39
|
+
"Config",
|
|
40
|
+
"ConfigError",
|
|
41
|
+
"DebugOption",
|
|
42
|
+
"FloatOption",
|
|
43
|
+
"IntOption",
|
|
44
|
+
"Node",
|
|
45
|
+
"Option",
|
|
46
|
+
"RawOption",
|
|
47
|
+
"State",
|
|
48
|
+
"StateVar",
|
|
49
|
+
"Tree",
|
|
50
|
+
"ViModeOption",
|
|
51
|
+
"register_argparser",
|
|
52
|
+
"register_config",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
importlib.import_module(".builtins", package=__package__)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Implementation of command line application."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
|
|
5
|
+
from .afterconn import Afterconn
|
|
6
|
+
from .args import args_apply, args_parse
|
|
7
|
+
from .cli import run
|
|
8
|
+
from .client import Client
|
|
9
|
+
from .config import load_config
|
|
10
|
+
from .plugins import load_plugins
|
|
11
|
+
from .state import State
|
|
12
|
+
from .url import Url
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def main() -> None:
|
|
16
|
+
"""Application's entrypoint."""
|
|
17
|
+
load_plugins()
|
|
18
|
+
argsgens, args = args_parse()
|
|
19
|
+
state = State()
|
|
20
|
+
load_config(args.config, state)
|
|
21
|
+
args_apply(argsgens, args, state)
|
|
22
|
+
state.cache_load(Url(state).cache_path())
|
|
23
|
+
|
|
24
|
+
async def async_main() -> None:
|
|
25
|
+
client = await Client.connect(Url(state).url, state=state)
|
|
26
|
+
await Afterconn(state).run(client)
|
|
27
|
+
await run(client)
|
|
28
|
+
if client.client.connected:
|
|
29
|
+
await client.disconnect()
|
|
30
|
+
|
|
31
|
+
asyncio.run(async_main())
|
|
32
|
+
state.cache_dump(Url(state).cache_path())
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if __name__ == "__main__":
|
|
36
|
+
main()
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""The after connection tasks."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import collections.abc
|
|
5
|
+
import typing
|
|
6
|
+
|
|
7
|
+
from .args import ArgsParseFuncGenT, register_argparser
|
|
8
|
+
from .client import Client, SHVPath
|
|
9
|
+
from .cliitems import CliItems
|
|
10
|
+
from .scan import scan_nodes
|
|
11
|
+
from .state import StateVar
|
|
12
|
+
|
|
13
|
+
AfterConnT: typing.TypeAlias = collections.abc.Callable[
|
|
14
|
+
[Client], collections.abc.Coroutine[None, None, None]
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Afterconn(StateVar, list[AfterConnT]):
|
|
19
|
+
"""The set of operations to be performed right after connection."""
|
|
20
|
+
|
|
21
|
+
async def run(self, client: Client) -> None:
|
|
22
|
+
"""Run the steps setup to be performed after connection at startup."""
|
|
23
|
+
for func in self:
|
|
24
|
+
await func(client)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@register_argparser
|
|
28
|
+
def _argparser(parser: argparse.ArgumentParser) -> ArgsParseFuncGenT:
|
|
29
|
+
parser.add_argument(
|
|
30
|
+
"-s",
|
|
31
|
+
"--subscribe",
|
|
32
|
+
action="append",
|
|
33
|
+
default=[],
|
|
34
|
+
help="Automatic subscription right after connection.",
|
|
35
|
+
)
|
|
36
|
+
parser.add_argument(
|
|
37
|
+
"--scan",
|
|
38
|
+
action="store_true",
|
|
39
|
+
help="Perform scan as a first action right after connect.",
|
|
40
|
+
)
|
|
41
|
+
parser.add_argument(
|
|
42
|
+
"--scan-depth",
|
|
43
|
+
type=int,
|
|
44
|
+
default=3,
|
|
45
|
+
help="Depth of the scan performed if --scan is used.",
|
|
46
|
+
)
|
|
47
|
+
args, state = yield
|
|
48
|
+
|
|
49
|
+
async def afterconn(client: Client) -> None:
|
|
50
|
+
for ri in args.subscribe:
|
|
51
|
+
await client.subscribe(CliItems.extend_ri(ri))
|
|
52
|
+
if args.scan:
|
|
53
|
+
await scan_nodes(client, SHVPath(""), args.scan_dept)
|
|
54
|
+
|
|
55
|
+
Afterconn(state).append(afterconn)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Argument parser wrapper for the SHVCLI."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import collections.abc
|
|
5
|
+
import contextlib
|
|
6
|
+
import pathlib
|
|
7
|
+
import typing
|
|
8
|
+
|
|
9
|
+
from .__version__ import VERSION
|
|
10
|
+
from .state import State
|
|
11
|
+
|
|
12
|
+
ArgsParseFuncGenT: typing.TypeAlias = collections.abc.Generator[
|
|
13
|
+
None, tuple[argparse.Namespace, State], None
|
|
14
|
+
]
|
|
15
|
+
ArgsparseFuncT: typing.TypeAlias = collections.abc.Callable[
|
|
16
|
+
[argparse.ArgumentParser], ArgsParseFuncGenT
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
registered_functions: list[ArgsparseFuncT] = []
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def register_argparser(func: ArgsparseFuncT) -> None:
|
|
23
|
+
"""Decorate function to register it to be called when arguments are being parsed."""
|
|
24
|
+
registered_functions.append(func)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def args_parse() -> tuple[tuple[ArgsParseFuncGenT, ...], argparse.Namespace]:
|
|
28
|
+
"""Parse passed arguments and return result."""
|
|
29
|
+
parser = argparse.ArgumentParser(prog="shvcli", description="Silicon Heaven CLI")
|
|
30
|
+
parser.add_argument("--version", action="version", version="%(prog)s " + VERSION)
|
|
31
|
+
parser.add_argument(
|
|
32
|
+
"-c",
|
|
33
|
+
"--config",
|
|
34
|
+
action="append",
|
|
35
|
+
type=pathlib.Path,
|
|
36
|
+
default=[pathlib.Path("/etc/shvcli.toml"), pathlib.Path("~/.shvcli.toml")],
|
|
37
|
+
)
|
|
38
|
+
gens = tuple(func(parser) for func in registered_functions)
|
|
39
|
+
for gen in gens:
|
|
40
|
+
next(gen)
|
|
41
|
+
args = parser.parse_args()
|
|
42
|
+
return gens, args
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def args_apply(
|
|
46
|
+
gens: tuple[ArgsParseFuncGenT, ...], args: argparse.Namespace, state: State
|
|
47
|
+
) -> None:
|
|
48
|
+
"""Apply parsed arguments on the given state.
|
|
49
|
+
|
|
50
|
+
The parsed arguments should be applied after configuration but
|
|
51
|
+
configuration loading needs to be influenced by arguments and thus split
|
|
52
|
+
arguments parsing to the parsing and application phase.
|
|
53
|
+
"""
|
|
54
|
+
for gen in gens:
|
|
55
|
+
with contextlib.suppress(StopIteration):
|
|
56
|
+
gen.send((args, state))
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Builtin methods glue code so they can be defined separatelly."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import abc
|
|
6
|
+
import collections.abc
|
|
7
|
+
import inspect
|
|
8
|
+
import typing
|
|
9
|
+
|
|
10
|
+
from prompt_toolkit.completion import Completion
|
|
11
|
+
|
|
12
|
+
from .client import Client
|
|
13
|
+
from .cliitems import CliItems
|
|
14
|
+
from .state import State, StateVar
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Builtin(abc.ABC):
|
|
18
|
+
"""The single builtin definition."""
|
|
19
|
+
|
|
20
|
+
builtins: typing.Final[list[type[Builtin]]] = []
|
|
21
|
+
|
|
22
|
+
def __init_subclass__(cls, *args: typing.Any, **kwargs: typing.Any) -> None: # noqa: ANN401
|
|
23
|
+
super().__init_subclass__(*args, **kwargs)
|
|
24
|
+
Builtin.builtins.append(cls)
|
|
25
|
+
|
|
26
|
+
def __init__(self, builtins: Builtins, state: State) -> None:
|
|
27
|
+
self.state = state
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
@abc.abstractmethod
|
|
31
|
+
def description(self) -> tuple[str, str]:
|
|
32
|
+
"""The provider of the description of this builtin.
|
|
33
|
+
|
|
34
|
+
:return: The first string is description of arguments expected by
|
|
35
|
+
builtin and the second one is the builtin description.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def completion( # noqa: PLR6301
|
|
39
|
+
self, items: CliItems, client: Client
|
|
40
|
+
) -> collections.abc.Iterable[Completion]:
|
|
41
|
+
"""Parameter completion for this builtin."""
|
|
42
|
+
return tuple()
|
|
43
|
+
|
|
44
|
+
async def completion_async( # noqa: PLR6301
|
|
45
|
+
self, items: CliItems, client: Client
|
|
46
|
+
) -> collections.abc.AsyncGenerator[Completion, None]:
|
|
47
|
+
"""Asynchronous parameter completion for this builtin.
|
|
48
|
+
|
|
49
|
+
This is used only if :class:`AutoProbeOption` is enabled.
|
|
50
|
+
|
|
51
|
+
It is common that this only fetches the required data with client and
|
|
52
|
+
the completion is performed in :meth:`completion` only.
|
|
53
|
+
"""
|
|
54
|
+
return
|
|
55
|
+
yield # type: ignore
|
|
56
|
+
|
|
57
|
+
def validate(self, items: CliItems, client: Client) -> None: # noqa: PLR6301
|
|
58
|
+
"""Validate the parameter for this builtin."""
|
|
59
|
+
return
|
|
60
|
+
|
|
61
|
+
async def validate_async(self, items: CliItems, client: Client) -> None: # noqa: PLR6301
|
|
62
|
+
"""Asynchronously validate the parameter for this builtin.
|
|
63
|
+
|
|
64
|
+
This is used only if :class:`AutoProbeOption` is enabled.
|
|
65
|
+
|
|
66
|
+
It is common that this only fetches the required data with client and
|
|
67
|
+
the validation is performed in :meth:`validate` only. SHVCLI also
|
|
68
|
+
always uses completion and validation together and because completion
|
|
69
|
+
happens alongside with validation it is rather common to do this
|
|
70
|
+
probing in the :meth:`completion_async` only.
|
|
71
|
+
"""
|
|
72
|
+
return
|
|
73
|
+
|
|
74
|
+
@abc.abstractmethod
|
|
75
|
+
async def run(self, items: CliItems, client: Client) -> None:
|
|
76
|
+
"""Run the builtin."""
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class Builtins(StateVar, dict[str, Builtin]):
|
|
80
|
+
"""All initialized builtins."""
|
|
81
|
+
|
|
82
|
+
def __init__(self, state: State) -> None:
|
|
83
|
+
super().__init__(state)
|
|
84
|
+
for builtin in Builtin.builtins:
|
|
85
|
+
if not inspect.isabstract(builtin):
|
|
86
|
+
builtin(self, state)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""All standard builtins.
|
|
2
|
+
|
|
3
|
+
This module is imported in the top level init and thus all builtins imported
|
|
4
|
+
here are automatically registered.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .broker import BuiltinSubscribe, BuiltinSubscriptions, BuiltinUnsubscribe
|
|
8
|
+
from .cd import BuiltinCD
|
|
9
|
+
from .file import BuiltinDownload, BuiltinUpload, BuiltinVerify
|
|
10
|
+
from .help import BuiltinHelp
|
|
11
|
+
from .scan import BuiltinScan
|
|
12
|
+
from .set import BuiltinSet
|
|
13
|
+
from .tree import BuiltinTree
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"BuiltinCD",
|
|
17
|
+
"BuiltinDownload",
|
|
18
|
+
"BuiltinHelp",
|
|
19
|
+
"BuiltinScan",
|
|
20
|
+
"BuiltinSet",
|
|
21
|
+
"BuiltinSubscribe",
|
|
22
|
+
"BuiltinSubscriptions",
|
|
23
|
+
"BuiltinTree",
|
|
24
|
+
"BuiltinUnsubscribe",
|
|
25
|
+
"BuiltinUpload",
|
|
26
|
+
"BuiltinVerify",
|
|
27
|
+
]
|