shvcli 0.6.2__tar.gz → 0.8.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 (61) hide show
  1. {shvcli-0.6.2/shvcli.egg-info → shvcli-0.8.0}/PKG-INFO +54 -18
  2. {shvcli-0.6.2 → shvcli-0.8.0}/README.rst +49 -13
  3. {shvcli-0.6.2 → shvcli-0.8.0}/pyproject.toml +5 -4
  4. shvcli-0.8.0/shvcli/__init__.py +55 -0
  5. shvcli-0.8.0/shvcli/__main__.py +35 -0
  6. shvcli-0.8.0/shvcli/__setuptools__.py +18 -0
  7. shvcli-0.8.0/shvcli/__version__.py +24 -0
  8. shvcli-0.8.0/shvcli/afterconn.py +55 -0
  9. shvcli-0.8.0/shvcli/args.py +56 -0
  10. shvcli-0.8.0/shvcli/builtin.py +86 -0
  11. shvcli-0.8.0/shvcli/builtins/__init__.py +29 -0
  12. shvcli-0.8.0/shvcli/builtins/broker.py +100 -0
  13. shvcli-0.8.0/shvcli/builtins/cd.py +37 -0
  14. shvcli-0.8.0/shvcli/builtins/file.py +128 -0
  15. shvcli-0.8.0/shvcli/builtins/help.py +58 -0
  16. shvcli-0.8.0/shvcli/builtins/history.py +146 -0
  17. shvcli-0.8.0/shvcli/builtins/scan.py +41 -0
  18. shvcli-0.8.0/shvcli/builtins/set.py +70 -0
  19. shvcli-0.8.0/shvcli/builtins/tree.py +66 -0
  20. shvcli-0.8.0/shvcli/cli.py +184 -0
  21. shvcli-0.8.0/shvcli/client.py +129 -0
  22. shvcli-0.8.0/shvcli/cliitems.py +91 -0
  23. shvcli-0.8.0/shvcli/complet.py +86 -0
  24. shvcli-0.8.0/shvcli/config.py +106 -0
  25. shvcli-0.8.0/shvcli/file.py +71 -0
  26. shvcli-0.8.0/shvcli/lsdir.py +128 -0
  27. shvcli-0.8.0/shvcli/oauth.py +75 -0
  28. shvcli-0.8.0/shvcli/option.py +267 -0
  29. shvcli-0.8.0/shvcli/options.py +168 -0
  30. {shvcli-0.6.2 → shvcli-0.8.0}/shvcli/scan.py +7 -7
  31. shvcli-0.8.0/shvcli/state.py +98 -0
  32. shvcli-0.8.0/shvcli/tools/__init__.py +1 -0
  33. shvcli-0.8.0/shvcli/tools/complet.py +60 -0
  34. shvcli-0.6.2/shvcli/tools.py → shvcli-0.8.0/shvcli/tools/print.py +23 -31
  35. shvcli-0.8.0/shvcli/tree.py +130 -0
  36. shvcli-0.8.0/shvcli/url.py +184 -0
  37. shvcli-0.8.0/shvcli/valid.py +78 -0
  38. {shvcli-0.6.2 → shvcli-0.8.0/shvcli.egg-info}/PKG-INFO +54 -18
  39. shvcli-0.8.0/shvcli.egg-info/SOURCES.txt +45 -0
  40. {shvcli-0.6.2 → shvcli-0.8.0}/shvcli.egg-info/requires.txt +2 -1
  41. shvcli-0.6.2/shvcli/__init__.py +0 -5
  42. shvcli-0.6.2/shvcli/__main__.py +0 -62
  43. shvcli-0.6.2/shvcli/__version__.py +0 -26
  44. shvcli-0.6.2/shvcli/builtin.py +0 -132
  45. shvcli-0.6.2/shvcli/builtin_impl.py +0 -193
  46. shvcli-0.6.2/shvcli/cli.py +0 -138
  47. shvcli-0.6.2/shvcli/client.py +0 -210
  48. shvcli-0.6.2/shvcli/complet.py +0 -78
  49. shvcli-0.6.2/shvcli/complet_tools.py +0 -64
  50. shvcli-0.6.2/shvcli/config.py +0 -176
  51. shvcli-0.6.2/shvcli/lsdir.py +0 -145
  52. shvcli-0.6.2/shvcli/parse.py +0 -79
  53. shvcli-0.6.2/shvcli/valid.py +0 -41
  54. shvcli-0.6.2/shvcli.egg-info/SOURCES.txt +0 -26
  55. {shvcli-0.6.2 → shvcli-0.8.0}/LICENSE +0 -0
  56. {shvcli-0.6.2 → shvcli-0.8.0}/setup.cfg +0 -0
  57. {shvcli-0.6.2 → shvcli-0.8.0}/shvcli/plugins.py +0 -0
  58. {shvcli-0.6.2 → shvcli-0.8.0}/shvcli/py.typed +0 -0
  59. {shvcli-0.6.2 → shvcli-0.8.0}/shvcli.egg-info/dependency_links.txt +0 -0
  60. {shvcli-0.6.2 → shvcli-0.8.0}/shvcli.egg-info/entry_points.txt +0 -0
  61. {shvcli-0.6.2 → shvcli-0.8.0}/shvcli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: shvcli
3
- Version: 0.6.2
3
+ Version: 0.8.0
4
4
  Summary: Silicon Heaven CLI access application
5
5
  Author: Elektroline a.s.
6
6
  License: MIT License
@@ -27,8 +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
- Classifier: Programming Language :: Python :: 3
32
30
  Classifier: Operating System :: OS Independent
33
31
  Classifier: Environment :: Console
34
32
  Classifier: Intended Audience :: End Users/Desktop
@@ -38,10 +36,12 @@ Classifier: Topic :: Terminals
38
36
  Requires-Python: >=3.11
39
37
  Description-Content-Type: text/x-rst
40
38
  License-File: LICENSE
41
- Requires-Dist: pyshv>=0.8.0
39
+ Requires-Dist: pyshv>=0.10.0
42
40
  Requires-Dist: prompt_toolkit
43
41
  Requires-Dist: pygments
44
42
  Requires-Dist: pyxdg
43
+ Requires-Dist: more-itertools
44
+ Dynamic: license-file
45
45
 
46
46
  =====================================
47
47
  Silicon Heaven CLI access application
@@ -101,20 +101,25 @@ An example of usage:
101
101
  .app> /:
102
102
  >
103
103
 
104
+ .. TIP::
105
+ The validation that is performed by SHVCLI is best effort and sometimes you
106
+ might need to submit call that is considered invalid by SHVCLI. For that
107
+ reason you can use `Ctrl+o` shortcut instead of pressing enter key.
108
+
104
109
 
105
110
  Configuration file
106
111
  ------------------
107
112
 
108
- Tool reads configuration from files ``/etc/shvcli.ini`` and ``~/.shvcli.ini``.
109
- They are in INI file format and the following sections are supported:
113
+ Tool reads configuration from files ``/etc/shvcli.toml`` and ``~/.shvcli.toml``.
114
+ They are in TOML file format and the following sections are supported:
110
115
 
111
116
  **hosts**: That provides mapping from some name to RPC URL.
112
117
 
113
118
  **hosts-shell**: That is same as **hosts** with exception that URL is passed
114
119
  through your local Shell to expand any variables or command substitutions.
115
120
 
116
- **config**: That allows you to set some initial configuration that can be also
117
- switched in runtime. The following options are available:
121
+ **option**: That allows you to set initial setting for runtime options. The
122
+ following options are available without any plugins:
118
123
 
119
124
  * **vimode**: If Vi input mode should be used for command line input. The
120
125
  default is ``false``.
@@ -137,16 +142,16 @@ switched in runtime. The following options are available:
137
142
  be also overwhelming. The default is ``false``. It is beneficial to disable
138
143
  the **autobrobe** once you enable debug because otherwise output on CLI will
139
144
  be mangled on completion.
140
- * **cache**: Controls if cache is preserved between invocations. Cache is
141
- separated based on the connection URL and stored in files in
142
- ``$XDG_CACHE_HOME/shvcli``. The default is ``true``.
143
- * **call_attempts**: Number of attempts before method call is abandoned and
144
- timeout is reported. This makes the total time multiple of **call_timeout**.
145
- * **call_timeout**: Timeout in seconds before call attempt is abandoned. Based
146
- on the **call_attempts** call is attempted again or timeout is reported.
147
- * **autoget_timeout**: Timeout in seconds before call that is part of autoget
145
+ * **call_query_timeout**: Timeout in seconds for status request query. The
146
+ shorter time will result in faster request lost detection while very short
147
+ time will load SHV network too much.
148
+ * **call_retry_timeout**: Timeout in seconds when call request is sent again if
149
+ no response is received. This is not applied if query is and thus this mostly
150
+ is used only in case when method doesn't support delayed responses.
151
+ * **autoget_timeout**: Timeout in seconds for call that is part of autoget
148
152
  functionality.
149
-
153
+ * **history_count**: Integer number used for number of records requested at time
154
+ for ``!history`` builtin.
150
155
 
151
156
  Example configuration file:
152
157
 
@@ -200,6 +205,19 @@ disable ``raw`` you use ``noraw``). You can also add ``=true`` or ``=false``.
200
205
  The equal sign is also used with integer and floating point options. Without any
201
206
  configuration option it simply prints the current configuration.
202
207
 
208
+ **upload**: provides a way to copy local file to the RPC File node. The
209
+ parameter must be path to the local file to be uploaded.
210
+
211
+ **download**: provides a way to copy RPC File node data to local file. The
212
+ parameter must be path to the local file where data will be stored.
213
+
214
+ **verify**: provides a way to verify RPC File node against local file. The
215
+ parameter must be path to the local file used for the verification.
216
+
217
+ **history**: is helper to list recorded history of signals by ``.history`` API.
218
+ The listing is incremental in ``history_count`` configured number of records and
219
+ in the order from the newest ones.
220
+
203
221
 
204
222
  Special methods ``ls`` and ``dir``
205
223
  ----------------------------------
@@ -211,3 +229,21 @@ the fullest content.
211
229
  Their parameter is also handled in a special way. It is considered to be
212
230
  additional path suffix unless it is a valid CPON. This is allowed to match the
213
231
  common shells.
232
+
233
+ You can see ``raw`` option to disable this behavior.
234
+
235
+
236
+ OAuth2 login
237
+ ------------
238
+
239
+ SHVCLI supports non-standard login method OAuth2. This is not defined by SHV
240
+ standard. The non-standard URL query ``oauth2=y`` is accepted to perform the
241
+ OAuth2 login. The login is facilitated by web browser. SHVCLI will start server
242
+ on ``tcp://localhost:37719/`` to be able to receive token.
243
+
244
+
245
+ Plugins
246
+ -------
247
+
248
+ The support for external plugins is provided. These plugins are discovered using
249
+ 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.ini`` and ``~/.shvcli.ini``.
64
- They are in INI file format and the following sections are supported:
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
- **config**: That allows you to set some initial configuration that can be also
72
- switched in runtime. The following options are available:
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,16 +97,16 @@ 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
- * **cache**: Controls if cache is preserved between invocations. Cache is
96
- separated based on the connection URL and stored in files in
97
- ``$XDG_CACHE_HOME/shvcli``. The default is ``true``.
98
- * **call_attempts**: Number of attempts before method call is abandoned and
99
- timeout is reported. This makes the total time multiple of **call_timeout**.
100
- * **call_timeout**: Timeout in seconds before call attempt is abandoned. Based
101
- on the **call_attempts** call is attempted again or timeout is reported.
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
+ * **history_count**: Integer number used for number of records requested at time
109
+ for ``!history`` builtin.
105
110
 
106
111
  Example configuration file:
107
112
 
@@ -155,6 +160,19 @@ disable ``raw`` you use ``noraw``). You can also add ``=true`` or ``=false``.
155
160
  The equal sign is also used with integer and floating point options. Without any
156
161
  configuration option it simply prints the current configuration.
157
162
 
163
+ **upload**: provides a way to copy local file to the RPC File node. The
164
+ parameter must be path to the local file to be uploaded.
165
+
166
+ **download**: provides a way to copy RPC File node data to local file. The
167
+ parameter must be path to the local file where data will be stored.
168
+
169
+ **verify**: provides a way to verify RPC File node against local file. The
170
+ parameter must be path to the local file used for the verification.
171
+
172
+ **history**: is helper to list recorded history of signals by ``.history`` API.
173
+ The listing is incremental in ``history_count`` configured number of records and
174
+ in the order from the newest ones.
175
+
158
176
 
159
177
  Special methods ``ls`` and ``dir``
160
178
  ----------------------------------
@@ -166,3 +184,21 @@ the fullest content.
166
184
  Their parameter is also handled in a special way. It is considered to be
167
185
  additional path suffix unless it is a valid CPON. This is allowed to match the
168
186
  common shells.
187
+
188
+ You can see ``raw`` option to disable this behavior.
189
+
190
+
191
+ OAuth2 login
192
+ ------------
193
+
194
+ SHVCLI supports non-standard login method OAuth2. This is not defined by SHV
195
+ standard. The non-standard URL query ``oauth2=y`` is accepted to perform the
196
+ OAuth2 login. The login is facilitated by web browser. SHVCLI will start server
197
+ on ``tcp://localhost:37719/`` to be able to receive token.
198
+
199
+
200
+ Plugins
201
+ -------
202
+
203
+ The support for external plugins is provided. These plugins are discovered using
204
+ Python package metadata using the entry point ``shvcli.plugins``.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "shvcli"
3
- version = "0.6.2"
3
+ version = "0.8.0"
4
4
  description = "Silicon Heaven CLI access application"
5
5
  readme = "README.rst"
6
6
  license = {file = "LICENSE"}
@@ -9,8 +9,6 @@ authors = [
9
9
  ]
10
10
  classifiers = [
11
11
  "Development Status :: 4 - Beta",
12
- "License :: OSI Approved :: MIT License",
13
- "Programming Language :: Python :: 3",
14
12
  "Operating System :: OS Independent",
15
13
  "Environment :: Console",
16
14
  "Intended Audience :: End Users/Desktop",
@@ -20,10 +18,11 @@ classifiers = [
20
18
  ]
21
19
  requires-python = ">=3.11"
22
20
  dependencies = [
23
- "pyshv >= 0.8.0",
21
+ "pyshv >= 0.10.0",
24
22
  "prompt_toolkit",
25
23
  "pygments",
26
24
  "pyxdg",
25
+ "more-itertools",
27
26
  ]
28
27
 
29
28
  [project.urls]
@@ -39,6 +38,8 @@ build-backend = "setuptools.build_meta"
39
38
  [tool.setuptools.packages.find]
40
39
  [tool.setuptools.package-data]
41
40
  "*" = ["py.typed"]
41
+ [tool.setuptools.cmdclass]
42
+ build_py = "shvcli.__setuptools__.BuildPy"
42
43
 
43
44
  [tool.coverage.run]
44
45
  branch = true
@@ -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,35 @@
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 .config import load_config
9
+ from .plugins import load_plugins
10
+ from .state import State
11
+ from .url import Url
12
+
13
+
14
+ def main() -> None:
15
+ """Application's entrypoint."""
16
+ load_plugins()
17
+ argsgens, args = args_parse()
18
+ state = State()
19
+ load_config(args.config, state)
20
+ args_apply(argsgens, args, state)
21
+ state.cache_load(Url(state).cache_path())
22
+
23
+ async def async_main() -> None:
24
+ client = await Url(state).connect()
25
+ await Afterconn(state).run(client)
26
+ await run(client)
27
+ if client.client.connected:
28
+ await client.disconnect()
29
+
30
+ asyncio.run(async_main())
31
+ state.cache_dump(Url(state).cache_path())
32
+
33
+
34
+ if __name__ == "__main__":
35
+ main()
@@ -0,0 +1,18 @@
1
+ """Setuptools hook used to replace __version__.py file."""
2
+
3
+ import pathlib
4
+
5
+ from setuptools.command.build_py import build_py as _build_py
6
+
7
+
8
+ class BuildPy(_build_py):
9
+ """Custom package build step."""
10
+
11
+ def run(self) -> None: # noqa: D102
12
+ package = pathlib.Path(__file__).parent.name
13
+ buildlib = pathlib.Path(self.build_lib) / package
14
+ buildlib.mkdir(parents=True, exist_ok=True)
15
+ version = self.distribution.metadata.version
16
+ (buildlib / "__version__.py").write_text(f'VERSION = "{version}"\n')
17
+ super().run()
18
+ (buildlib / "__setuptools__.py").unlink()
@@ -0,0 +1,24 @@
1
+ """The loader of the version for source file only installation.
2
+
3
+ It looks for pyproject.toml file in upper directory and loads version from
4
+ there.
5
+
6
+ This file is overwritten during distribution build to contain only constant
7
+ VERSION. Please see __setuptools__.py for details.
8
+ """
9
+
10
+ import pathlib
11
+ import tomllib
12
+
13
+
14
+ def _get_version() -> str:
15
+ pyproject = pathlib.Path(__file__).parent.parent / "pyproject.toml"
16
+ if pyproject.exists():
17
+ with pyproject.open("rb") as f:
18
+ res = tomllib.load(f)["project"]["version"]
19
+ if isinstance(res, str):
20
+ return res
21
+ return "unknown"
22
+
23
+
24
+ VERSION = _get_version()
@@ -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,29 @@
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 .history import BuiltinHistory
12
+ from .scan import BuiltinScan
13
+ from .set import BuiltinSet
14
+ from .tree import BuiltinTree
15
+
16
+ __all__ = [
17
+ "BuiltinCD",
18
+ "BuiltinDownload",
19
+ "BuiltinHelp",
20
+ "BuiltinHistory",
21
+ "BuiltinScan",
22
+ "BuiltinSet",
23
+ "BuiltinSubscribe",
24
+ "BuiltinSubscriptions",
25
+ "BuiltinTree",
26
+ "BuiltinUnsubscribe",
27
+ "BuiltinUpload",
28
+ "BuiltinVerify",
29
+ ]