hspylib-clitt 0.9.27__tar.gz → 0.9.29__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.
Potentially problematic release.
This version of hspylib-clitt might be problematic. Click here for more details.
- {hspylib-clitt-0.9.27/hspylib_clitt.egg-info → hspylib-clitt-0.9.29}/PKG-INFO +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/README.md +1 -1
- hspylib-clitt-0.9.29/clitt/.version +1 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/__init__.py +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/__main__.py +46 -15
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/__init__.py +3 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/__init__.py +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/appman.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/appman_enums.py +6 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/templates/__init__.py +2 -2
- hspylib-clitt-0.9.29/clitt/addons/setman/__init__.py +16 -0
- hspylib-clitt-0.9.29/clitt/addons/setman/setman.py +203 -0
- hspylib-clitt-0.9.29/clitt/addons/setman/setman_config.py +38 -0
- hspylib-clitt-0.9.29/clitt/addons/setman/setman_entry.py +109 -0
- hspylib-clitt-0.9.29/clitt/addons/setman/setman_enums.py +55 -0
- hspylib-clitt-0.9.29/clitt/addons/setman/setman_repository.py +68 -0
- hspylib-clitt-0.9.29/clitt/addons/setman/setman_service.py +67 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/widman/__init__.py +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/widman/widget.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/widman/widget_entry.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/widman/widgets/__init__.py +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/widman/widgets/widget_free.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/widman/widgets/widget_punch.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/widman/widgets/widget_send_msg.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/widman/widgets/widget_time_calc.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/widman/widman.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/__init__.py +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/icons/__init__.py +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/icons/emojis/__init__.py +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/icons/emojis/emojis.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/icons/emojis/face_smiling.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/icons/font_awesome/__init__.py +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/icons/font_awesome/app_icons.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/icons/font_awesome/awesome.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/icons/font_awesome/control_icons.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/icons/font_awesome/dashboard_icons.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/icons/font_awesome/form_icons.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/icons/font_awesome/nav_icons.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/icons/font_awesome/widget_icons.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/__init__.py +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/mchoose/__init__.py +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/mchoose/menu_choose.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/mdashboard/__init__.py +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/menu/__init__.py +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/menu/tui_menu_item.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/minput/__init__.py +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/minput/minput.py +0 -15
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/mselect/__init__.py +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/mselect/menu_select.py +3 -3
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/table/__init__.py +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/tui_application.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/tui_component.py +5 -5
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/tui_preferences.py +1 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29/hspylib_clitt.egg-info}/PKG-INFO +2 -2
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/hspylib_clitt.egg-info/SOURCES.txt +7 -0
- hspylib-clitt-0.9.27/clitt/.version +0 -1
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/MANIFEST.in +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/__classpath__.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/templates/build.gradle.tpl +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/templates/classpath.py.tpl +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/templates/dependencies.hspd.tpl +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/templates/gitignore.tpl +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/templates/main.py.tpl +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/templates/main_qt.py.tpl +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/templates/main_qt_view.py.tpl +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/templates/main_qt_view.ui.tpl +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/templates/run.sh.tpl +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/templates/test_main.py.tpl +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/templates/usage.txt.tpl +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/addons/appman/templates/widget.py.tpl +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/mchoose/mchoose.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/mdashboard/dashboard_builder.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/mdashboard/dashboard_item.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/mdashboard/mdashboard.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/menu/tui_menu.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/menu/tui_menu_action.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/menu/tui_menu_factory.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/menu/tui_menu_ui.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/menu/tui_menu_utils.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/menu/tui_menu_view.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/minput/access_type.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/minput/form_builder.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/minput/form_field.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/minput/input_type.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/minput/input_validator.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/minput/menu_input.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/minput/minput_utils.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/mselect/mselect.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/core/tui/table/table_renderer.py +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/clitt/welcome.txt +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/hspylib_clitt.egg-info/dependency_links.txt +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/hspylib_clitt.egg-info/requires.txt +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/hspylib_clitt.egg-info/top_level.txt +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/setup.cfg +0 -0
- {hspylib-clitt-0.9.27 → hspylib-clitt-0.9.29}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hspylib-clitt
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.29
|
|
4
4
|
Summary: HsPyLib - CLI Terminal Tools
|
|
5
5
|
Home-page: https://github.com/yorevs/hspylib
|
|
6
6
|
Author: Hugo Saporetti Junior
|
|
@@ -30,7 +30,7 @@ Description-Content-Type: text/markdown
|
|
|
30
30
|
## Create professional CLI applications
|
|
31
31
|
|
|
32
32
|
[](LICENSE.md)
|
|
33
|
-
[](CHANGELOG.md#unreleased)
|
|
34
34
|
[](https://pypi.org/project/hspylib-cfman)
|
|
35
35
|
[](https://github.com/yorevs/hspylib)
|
|
36
36
|
[](https://gitter.im/hspylib/community)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
## Create professional CLI applications
|
|
4
4
|
|
|
5
5
|
[](LICENSE.md)
|
|
6
|
-
[](CHANGELOG.md#unreleased)
|
|
7
7
|
[](https://pypi.org/project/hspylib-cfman)
|
|
8
8
|
[](https://github.com/yorevs/hspylib)
|
|
9
9
|
[](https://gitter.im/hspylib/community)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.9.29
|
|
@@ -12,19 +12,23 @@
|
|
|
12
12
|
|
|
13
13
|
Copyright 2023, HsPyLib team
|
|
14
14
|
"""
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
from clitt.addons.appman.appman_enums import AppExtension, AppType
|
|
18
|
-
from clitt.addons.widman.widman import WidgetManager
|
|
19
|
-
from clitt.core.tui.tui_application import TUIApplication
|
|
15
|
+
import sys
|
|
16
|
+
|
|
20
17
|
from hspylib.core.enums.charset import Charset
|
|
21
18
|
from hspylib.core.enums.enumeration import Enumeration
|
|
22
19
|
from hspylib.core.tools.commons import run_dir, syserr
|
|
23
20
|
from hspylib.core.tools.text_tools import strip_linebreaks
|
|
24
21
|
from hspylib.modules.application.exit_status import ExitStatus
|
|
22
|
+
from hspylib.modules.application.parser_action import ParserAction
|
|
25
23
|
from hspylib.modules.application.version import Version
|
|
26
24
|
|
|
27
|
-
import
|
|
25
|
+
from clitt.__classpath__ import _Classpath
|
|
26
|
+
from clitt.addons.appman.appman import AppManager
|
|
27
|
+
from clitt.addons.appman.appman_enums import AppExtension, AppType
|
|
28
|
+
from clitt.addons.setman.setman import SetMan
|
|
29
|
+
from clitt.addons.setman.setman_enums import SetmanOps, SettingsType
|
|
30
|
+
from clitt.addons.widman.widman import WidgetManager
|
|
31
|
+
from clitt.core.tui.tui_application import TUIApplication
|
|
28
32
|
|
|
29
33
|
|
|
30
34
|
class Main(TUIApplication):
|
|
@@ -42,6 +46,7 @@ class Main(TUIApplication):
|
|
|
42
46
|
# fmt: off
|
|
43
47
|
APPMAN = 'appman'
|
|
44
48
|
WIDGETS = 'widgets'
|
|
49
|
+
SETMAN = 'setman'
|
|
45
50
|
# fmt: on
|
|
46
51
|
|
|
47
52
|
@property
|
|
@@ -65,19 +70,15 @@ class Main(TUIApplication):
|
|
|
65
70
|
'the destination directory. If omitted, the current directory will be used.',
|
|
66
71
|
nargs='?', default=self._run_dir) \
|
|
67
72
|
.add_parameter(
|
|
68
|
-
'app-name',
|
|
69
|
-
'the application name', nargs='?') \
|
|
73
|
+
'app-name', 'the application name', nargs='?') \
|
|
70
74
|
.add_parameter(
|
|
71
75
|
'app-type',
|
|
72
76
|
'the application type. Appman is going to scaffold a basic application based on the app type',
|
|
73
|
-
choices=
|
|
74
|
-
AppType.APP.value, AppType.QT_APP.value, AppType.WIDGET.value
|
|
75
|
-
], nargs='?') \
|
|
77
|
+
choices=AppType.choices(), nargs='?') \
|
|
76
78
|
.add_parameter(
|
|
77
79
|
'app-ext',
|
|
78
80
|
'"gradle" is going to initialize you project with gradle (requires gradle). '
|
|
79
|
-
'"git" is going to initialize a git repository (requires git)',
|
|
80
|
-
nargs='*') \
|
|
81
|
+
'"git" is going to initialize a git repository (requires git)', nargs='*') \
|
|
81
82
|
.argument(self.Addon.WIDGETS.val, 'app Widgets Manager: Execute an HsPyLib widget') \
|
|
82
83
|
.add_parameter(
|
|
83
84
|
'widget-name',
|
|
@@ -85,8 +86,26 @@ class Main(TUIApplication):
|
|
|
85
86
|
'presented in a dashboard',
|
|
86
87
|
nargs='?') \
|
|
87
88
|
.add_parameter(
|
|
88
|
-
'widget-args', "the widget's arguments (if applicable)",
|
|
89
|
-
|
|
89
|
+
'widget-args', "the widget's arguments (if applicable)", nargs='*') \
|
|
90
|
+
.argument(self.Addon.SETMAN.val, 'app Settings Manager: Manage your terminal settings') \
|
|
91
|
+
.add_parameter(
|
|
92
|
+
'operation',
|
|
93
|
+
'the operation to be performed against your settings. ',
|
|
94
|
+
choices=SetmanOps.choices()) \
|
|
95
|
+
.add_option(
|
|
96
|
+
'name', 'n', 'name',
|
|
97
|
+
'the settings name. ', nargs='?') \
|
|
98
|
+
.add_option(
|
|
99
|
+
'value', 'v', 'value',
|
|
100
|
+
'the settings value. ', nargs='?') \
|
|
101
|
+
.add_option(
|
|
102
|
+
'stype', 't', 'type',
|
|
103
|
+
'the settings type. ',
|
|
104
|
+
choices=SettingsType.choices()) \
|
|
105
|
+
.add_option(
|
|
106
|
+
'simple', 's', 'simple',
|
|
107
|
+
'display without formatting. ', action=ParserAction.STORE_TRUE) \
|
|
108
|
+
# fmt: on
|
|
90
109
|
|
|
91
110
|
def _main(self, *params, **kwargs) -> ExitStatus:
|
|
92
111
|
"""Main entry point handler."""
|
|
@@ -100,6 +119,8 @@ class Main(TUIApplication):
|
|
|
100
119
|
self.start_appman()
|
|
101
120
|
elif app == self.Addon.WIDGETS.val:
|
|
102
121
|
self.start_widman()
|
|
122
|
+
elif app == self.Addon.SETMAN.val:
|
|
123
|
+
self.start_setman()
|
|
103
124
|
else:
|
|
104
125
|
syserr(f"### Invalid Addon application: {app}")
|
|
105
126
|
self.usage(ExitStatus.FAILED)
|
|
@@ -138,6 +159,16 @@ class Main(TUIApplication):
|
|
|
138
159
|
app_ext.append(AppExtension.GIT)
|
|
139
160
|
addon.create(args.app_name, AppType.of_value(args.app_type), list(app_ext), args.dest_dir or run_dir())
|
|
140
161
|
|
|
162
|
+
def start_setman(self) -> None:
|
|
163
|
+
"""Start the Setman application."""
|
|
164
|
+
addon = SetMan(self)
|
|
165
|
+
op = SetmanOps.of_value(self.get_arg("operation"), ignore_case=True)
|
|
166
|
+
name = self.get_arg("name")
|
|
167
|
+
value = self.get_arg("value")
|
|
168
|
+
stype = self.get_arg("stype")
|
|
169
|
+
simple_fmt: bool = bool(self.get_arg("simple"))
|
|
170
|
+
addon.execute(op, name, value, SettingsType.of_value(stype) if stype else None, simple_fmt)
|
|
171
|
+
|
|
141
172
|
|
|
142
173
|
# Application entry point
|
|
143
174
|
if __name__ == "__main__":
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# _*_ coding: utf-8 _*_
|
|
2
2
|
#
|
|
3
|
-
# hspylib-clitt v0.9.
|
|
3
|
+
# hspylib-clitt v0.9.29
|
|
4
4
|
#
|
|
5
5
|
# Package: main.clitt.addons
|
|
6
6
|
"""Package initialization."""
|
|
7
7
|
|
|
8
8
|
__all__ = [
|
|
9
9
|
'appman',
|
|
10
|
+
'setman',
|
|
10
11
|
'widman'
|
|
11
12
|
]
|
|
12
|
-
__version__ = '0.9.
|
|
13
|
+
__version__ = '0.9.29'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# _*_ coding: utf-8 _*_
|
|
2
2
|
#
|
|
3
|
-
# hspylib-clitt v0.9.
|
|
3
|
+
# hspylib-clitt v0.9.29
|
|
4
4
|
#
|
|
5
5
|
# Package: main.clitt.addons.appman
|
|
6
6
|
"""Package initialization."""
|
|
@@ -10,4 +10,4 @@ __all__ = [
|
|
|
10
10
|
'appman_enums',
|
|
11
11
|
'templates'
|
|
12
12
|
]
|
|
13
|
-
__version__ = '0.9.
|
|
13
|
+
__version__ = '0.9.29'
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
|
|
4
4
|
"""
|
|
5
|
-
@project: HsPyLib
|
|
5
|
+
@project: HsPyLib-Clitt
|
|
6
6
|
@package: clitt.addons.appman
|
|
7
7
|
@file: appman_enums.py
|
|
8
8
|
@created: Fri, 29 Jul 2022
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
Copyright 2023, HsPyLib team
|
|
14
14
|
"""
|
|
15
|
+
from typing import List
|
|
15
16
|
|
|
16
17
|
from hspylib.core.enums.enumeration import Enumeration
|
|
17
18
|
|
|
@@ -33,3 +34,7 @@ class AppType(Enumeration):
|
|
|
33
34
|
QT_APP = 'qt-app'
|
|
34
35
|
WIDGET = 'widget'
|
|
35
36
|
# fmt: on
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def choices() -> List[str]:
|
|
40
|
+
return AppType.values()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# _*_ coding: utf-8 _*_
|
|
2
|
+
#
|
|
3
|
+
# hspylib-clitt v0.9.29
|
|
4
|
+
#
|
|
5
|
+
# Package: main.clitt.addons.setman
|
|
6
|
+
"""Package initialization."""
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
'setman',
|
|
10
|
+
'setman_config',
|
|
11
|
+
'setman_entry',
|
|
12
|
+
'setman_enums',
|
|
13
|
+
'setman_repository',
|
|
14
|
+
'setman_service'
|
|
15
|
+
]
|
|
16
|
+
__version__ = '0.9.29'
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
@project: HsPyLib
|
|
6
|
+
@package: clitt.addons.setman
|
|
7
|
+
@file: setman.py
|
|
8
|
+
@created: Fri, 29 May 2023
|
|
9
|
+
@author: "<B>H</B>ugo <B>S</B>aporetti <B>J</B>unior")"
|
|
10
|
+
@site: "https://github.com/yorevs/hspylib")
|
|
11
|
+
@license: MIT - Please refer to <https://opensource.org/licenses/MIT>
|
|
12
|
+
|
|
13
|
+
Copyright 2023, HsPyLib team
|
|
14
|
+
"""
|
|
15
|
+
import atexit
|
|
16
|
+
import binascii
|
|
17
|
+
import contextlib
|
|
18
|
+
import logging as log
|
|
19
|
+
import os
|
|
20
|
+
import uuid
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
from datasource.identity import Identity
|
|
24
|
+
from hspylib.core.enums.charset import Charset
|
|
25
|
+
from hspylib.core.exception.exceptions import ApplicationError
|
|
26
|
+
from hspylib.core.metaclass.singleton import Singleton
|
|
27
|
+
from hspylib.core.tools.commons import file_is_not_empty, safe_delete_file, syserr, sysout, touch_file
|
|
28
|
+
from hspylib.modules.application.application import Application
|
|
29
|
+
from hspylib.modules.security.security import decode_file, encode_file
|
|
30
|
+
|
|
31
|
+
from clitt.addons.setman.setman_config import SetmanConfig
|
|
32
|
+
from clitt.addons.setman.setman_entry import SetmanEntry
|
|
33
|
+
from clitt.addons.setman.setman_enums import SetmanOps, SettingsType
|
|
34
|
+
from clitt.addons.setman.setman_service import SetmanService
|
|
35
|
+
from clitt.core.tui.table.table_renderer import TableRenderer
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class SetMan(metaclass=Singleton):
|
|
39
|
+
|
|
40
|
+
RESOURCE_DIR = os.environ.get('HHS_DIR', os.environ.get('HOME', '~/'))
|
|
41
|
+
|
|
42
|
+
SETMAN_CONFIG_FILE = f"setman.properties"
|
|
43
|
+
|
|
44
|
+
SETMAN_DB_FILE = f"{RESOURCE_DIR}/.setman-db"
|
|
45
|
+
|
|
46
|
+
def __init__(self, parent_app: Application) -> None:
|
|
47
|
+
self._parent_app = parent_app
|
|
48
|
+
cfg_file = f"{self.RESOURCE_DIR}/{self.SETMAN_CONFIG_FILE}"
|
|
49
|
+
if not file_is_not_empty(cfg_file):
|
|
50
|
+
self._setup_db(cfg_file)
|
|
51
|
+
self._configs = SetmanConfig(self.RESOURCE_DIR, self.SETMAN_CONFIG_FILE)
|
|
52
|
+
self._service = SetmanService(self.configs)
|
|
53
|
+
if not file_is_not_empty(self.configs.database):
|
|
54
|
+
self._create_new_database()
|
|
55
|
+
self._is_open = False
|
|
56
|
+
safe_delete_file(self.configs.encoded_file)
|
|
57
|
+
safe_delete_file(self.configs.decoded_file)
|
|
58
|
+
|
|
59
|
+
def __str__(self):
|
|
60
|
+
data = set(self._service.list())
|
|
61
|
+
vault_str = ""
|
|
62
|
+
for entry in data:
|
|
63
|
+
vault_str += entry.key
|
|
64
|
+
return vault_str
|
|
65
|
+
|
|
66
|
+
def __repr__(self):
|
|
67
|
+
return str(self)
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def configs(self) -> SetmanConfig:
|
|
71
|
+
return self._configs
|
|
72
|
+
|
|
73
|
+
def execute(
|
|
74
|
+
self,
|
|
75
|
+
operation: SetmanOps,
|
|
76
|
+
name: str | None,
|
|
77
|
+
value: Any | None,
|
|
78
|
+
stype: SettingsType = None,
|
|
79
|
+
simple_fmt: bool = False) -> None:
|
|
80
|
+
|
|
81
|
+
"""Execute the specified operation."""
|
|
82
|
+
log.debug(f"{operation} Name: {name or '*'} Value: {value or '-'} SettingsType: {stype or '*'}")
|
|
83
|
+
atexit.register(self._close_db)
|
|
84
|
+
with self._open_db():
|
|
85
|
+
match operation:
|
|
86
|
+
case SetmanOps.LIST:
|
|
87
|
+
self._list_settings()
|
|
88
|
+
case SetmanOps.SEARCH:
|
|
89
|
+
self._search_settings(name or '%', stype, simple_fmt)
|
|
90
|
+
case SetmanOps.SET:
|
|
91
|
+
self._add_setting(name, value, stype)
|
|
92
|
+
case SetmanOps.GET:
|
|
93
|
+
self._get_setting(name, simple_fmt)
|
|
94
|
+
case SetmanOps.DEL:
|
|
95
|
+
self._del_setting(name)
|
|
96
|
+
case SetmanOps.TRUNCATE:
|
|
97
|
+
self._service.truncate_settings_db()
|
|
98
|
+
sysout('%EOL%%ORANGE%!!! All system settings have been removed !!!%EOL%')
|
|
99
|
+
|
|
100
|
+
@contextlib.contextmanager
|
|
101
|
+
def _open_db(self) -> None:
|
|
102
|
+
"""Decode and open the SQL lite database file. Return the context to manipulate it."""
|
|
103
|
+
try:
|
|
104
|
+
if not self._is_open:
|
|
105
|
+
self._is_open = True
|
|
106
|
+
self._decode_db()
|
|
107
|
+
log.debug("Settings database open")
|
|
108
|
+
yield self._is_open
|
|
109
|
+
except (UnicodeDecodeError, binascii.Error) as err:
|
|
110
|
+
log.error("Failed to open settings file => %s", err)
|
|
111
|
+
yield None
|
|
112
|
+
except Exception as err:
|
|
113
|
+
raise ApplicationError(f"Unable to open settings file => {self.configs.database}", err) from err
|
|
114
|
+
finally:
|
|
115
|
+
self._close_db()
|
|
116
|
+
|
|
117
|
+
def _close_db(self) -> None:
|
|
118
|
+
"""Encode and open the SQL lite database file. Return the context to manipulate it."""
|
|
119
|
+
try:
|
|
120
|
+
if self._is_open:
|
|
121
|
+
self._is_open = False
|
|
122
|
+
self._encode_db()
|
|
123
|
+
log.debug("Settings database closed")
|
|
124
|
+
except (UnicodeDecodeError, binascii.Error) as err:
|
|
125
|
+
log.error("Failed to close settings file => %s", err)
|
|
126
|
+
except Exception as err:
|
|
127
|
+
raise ApplicationError(f"Unable to close settings file => {self.configs.database}", err) from err
|
|
128
|
+
|
|
129
|
+
def _encode_db(self) -> None:
|
|
130
|
+
"""Decode the Base64 encoded database file."""
|
|
131
|
+
if file_is_not_empty(self.configs.database):
|
|
132
|
+
encoded = f"{self.configs.database}-encoded"
|
|
133
|
+
encode_file(self.configs.database, encoded, binary=True)
|
|
134
|
+
os.rename(encoded, self.configs.database)
|
|
135
|
+
self._is_open = False
|
|
136
|
+
log.debug("Settings file is encoded")
|
|
137
|
+
|
|
138
|
+
def _decode_db(self) -> None:
|
|
139
|
+
"""Base64 encode the database file."""
|
|
140
|
+
if file_is_not_empty(self.configs.database):
|
|
141
|
+
decoded = f"{self.configs.database}-decoded"
|
|
142
|
+
decode_file(self.configs.database, decoded, binary=True)
|
|
143
|
+
os.rename(decoded, self.configs.database)
|
|
144
|
+
self._is_open = True
|
|
145
|
+
log.debug("Settings file is decoded")
|
|
146
|
+
|
|
147
|
+
def _list_settings(self) -> None:
|
|
148
|
+
"""List all database settings using as a formatted table."""
|
|
149
|
+
headers = ["uuid", "name", "value", "settings type", "modified"]
|
|
150
|
+
data = list(map(lambda e: e.values, self._service.list()))
|
|
151
|
+
tr = TableRenderer(headers, data, "Systems Settings")
|
|
152
|
+
tr.adjust_auto_fit()
|
|
153
|
+
tr.set_header_alignment(TableRenderer.TextAlignment.CENTER)
|
|
154
|
+
tr.set_cell_alignment(TableRenderer.TextAlignment.LEFT)
|
|
155
|
+
tr.render()
|
|
156
|
+
|
|
157
|
+
def _search_settings(self, name: str, stype: SettingsType, simple_fmt: bool) -> None:
|
|
158
|
+
"""Display all settings matching the name and settings type."""
|
|
159
|
+
data = list(map(lambda e: e.to_string(simple_fmt), self._service.search(name, stype)))
|
|
160
|
+
sysout(os.linesep.join(data))
|
|
161
|
+
|
|
162
|
+
def _del_setting(self, name: str) -> None:
|
|
163
|
+
"""Delete the specified setting."""
|
|
164
|
+
if name:
|
|
165
|
+
found = self._service.get(name)
|
|
166
|
+
if found:
|
|
167
|
+
self._service.remove(found)
|
|
168
|
+
sysout('%GREEN%Settings deleted: %ORANGE%', found.name)
|
|
169
|
+
else:
|
|
170
|
+
syserr('Settings not found: ', name)
|
|
171
|
+
|
|
172
|
+
def _get_setting(self, name: str, simple_fmt: bool) -> None:
|
|
173
|
+
"""Get the specified setting."""
|
|
174
|
+
if name:
|
|
175
|
+
found = self._service.get(name)
|
|
176
|
+
if found:
|
|
177
|
+
sysout(found.to_string(simple_fmt))
|
|
178
|
+
else:
|
|
179
|
+
syserr('Settings not found: ', name)
|
|
180
|
+
|
|
181
|
+
def _add_setting(self, name: str, value: Any, stype: SettingsType) -> None:
|
|
182
|
+
"""Upsert the specified setting."""
|
|
183
|
+
found = self._service.get(name)
|
|
184
|
+
entry = found or SetmanEntry(Identity(SetmanEntry.SetmanId(uuid.uuid4().hex)), name, value, stype)
|
|
185
|
+
if not name or not value or not stype:
|
|
186
|
+
entry = SetmanEntry.prompt(entry)
|
|
187
|
+
if entry:
|
|
188
|
+
self._service.save(entry)
|
|
189
|
+
sysout(f"%GREEN%Settings {'added' if not found else 'saved'}: %BLUE%", repr(entry))
|
|
190
|
+
|
|
191
|
+
def _create_new_database(self) -> bool:
|
|
192
|
+
"""Create the settings SQLite DB file."""
|
|
193
|
+
touch_file(self.configs.database)
|
|
194
|
+
self._service.create_settings_db()
|
|
195
|
+
log.info('Settings file has been created')
|
|
196
|
+
self._is_open = True
|
|
197
|
+
return os.path.exists(self.configs.database)
|
|
198
|
+
|
|
199
|
+
def _setup_db(self, filepath: str) -> bool:
|
|
200
|
+
"""Setup SetMan on the system."""
|
|
201
|
+
with open(filepath, "w+", encoding=Charset.UTF_8.val) as f_configs:
|
|
202
|
+
f_configs.write(f"hhs.setman.database = {self.SETMAN_DB_FILE} {os.linesep}")
|
|
203
|
+
return os.path.exists(filepath)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
@project: HsPyLib-Clitt
|
|
6
|
+
@package: clitt.addons.setman
|
|
7
|
+
@file: setman_config.py
|
|
8
|
+
@created: Mon, 5 Jun 2023
|
|
9
|
+
@author: <B>H</B>ugo <B>S</B>aporetti <B>J</B>unior"
|
|
10
|
+
@site: https://github.com/yorevs/hspylib
|
|
11
|
+
@license: MIT - Please refer to <https://opensource.org/licenses/MIT>
|
|
12
|
+
|
|
13
|
+
Copyright 2023, HsPyLib team
|
|
14
|
+
"""
|
|
15
|
+
from datasource.db_configuration import DBConfiguration
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SetmanConfig(DBConfiguration):
|
|
19
|
+
"""Holds the SetMan configurations."""
|
|
20
|
+
|
|
21
|
+
INSTANCE = None
|
|
22
|
+
|
|
23
|
+
def __init__(self, resource_dir: str, filename: str):
|
|
24
|
+
super().__init__(resource_dir, filename)
|
|
25
|
+
self._database = self["hhs.setman.database"]
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def database(self) -> str:
|
|
29
|
+
"""Return the SetMan database name."""
|
|
30
|
+
return self._database
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def encoded_file(self) -> str:
|
|
34
|
+
return f"{self.database}-encoded"
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def decoded_file(self) -> str:
|
|
38
|
+
return f"{self.database}-decoded"
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
@project: HsPyLib-Clitt
|
|
6
|
+
@package: clitt.addons.setman
|
|
7
|
+
@file: setman_entry.py
|
|
8
|
+
@created: Mon, 5 Jun 2023
|
|
9
|
+
@author: <B>H</B>ugo <B>S</B>aporetti <B>J</B>unior"
|
|
10
|
+
@site: https://github.com/yorevs/hspylib
|
|
11
|
+
@license: MIT - Please refer to <https://opensource.org/licenses/MIT>
|
|
12
|
+
|
|
13
|
+
Copyright 2023, HsPyLib team
|
|
14
|
+
"""
|
|
15
|
+
from collections import namedtuple
|
|
16
|
+
from textwrap import dedent
|
|
17
|
+
from typing import Any, Optional, Union
|
|
18
|
+
|
|
19
|
+
from datasource.crud_entity import CrudEntity
|
|
20
|
+
from datasource.identity import Identity
|
|
21
|
+
from hspylib.core.tools.text_tools import environ_name
|
|
22
|
+
from hspylib.core.zoned_datetime import now
|
|
23
|
+
|
|
24
|
+
from clitt.addons.setman.setman_enums import SettingsType
|
|
25
|
+
from clitt.core.tui.minput.menu_input import MenuInput
|
|
26
|
+
from clitt.core.tui.minput.minput import minput
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SetmanEntry(CrudEntity):
|
|
30
|
+
"""Represents the Setman domain object."""
|
|
31
|
+
|
|
32
|
+
SetmanId = namedtuple("SetmanId", ["uuid"])
|
|
33
|
+
|
|
34
|
+
# Setman entry display format.
|
|
35
|
+
_DISPLAY_FORMAT = dedent(
|
|
36
|
+
"""
|
|
37
|
+
[%BLUE%{}%NC%]:
|
|
38
|
+
Type: %GREEN%{}%NC%
|
|
39
|
+
Value: %GREEN%{}%NC%
|
|
40
|
+
Modified: %GREEN%{}%NC%
|
|
41
|
+
"""
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# Setman entry simple format.
|
|
45
|
+
_SIMPLE_FORMAT = "{}={}"
|
|
46
|
+
|
|
47
|
+
@staticmethod
|
|
48
|
+
def prompt(entry: Union["SetmanEntry", None] = None) -> Optional["SetmanEntry"]:
|
|
49
|
+
"""Create a vault entry from a form input."""
|
|
50
|
+
|
|
51
|
+
entry = entry or SetmanEntry()
|
|
52
|
+
# fmt: off
|
|
53
|
+
form_fields = MenuInput.builder() \
|
|
54
|
+
.field() \
|
|
55
|
+
.label('Name') \
|
|
56
|
+
.min_max_length(1, 60) \
|
|
57
|
+
.value(entry.name) \
|
|
58
|
+
.build() \
|
|
59
|
+
.field() \
|
|
60
|
+
.label('Value') \
|
|
61
|
+
.min_max_length(1, 60) \
|
|
62
|
+
.value(entry.value) \
|
|
63
|
+
.build() \
|
|
64
|
+
.field() \
|
|
65
|
+
.label('Type') \
|
|
66
|
+
.itype('select') \
|
|
67
|
+
.dest('stype') \
|
|
68
|
+
.value(SettingsType.selectables(entry.stype) if entry.stype else None) \
|
|
69
|
+
.build() \
|
|
70
|
+
.build()
|
|
71
|
+
# fmt: on
|
|
72
|
+
|
|
73
|
+
if result := minput(form_fields, "Please fill the settings details"):
|
|
74
|
+
entry.name = result.name
|
|
75
|
+
entry.value = result.value
|
|
76
|
+
entry.stype = result.stype
|
|
77
|
+
entry.modified = now()
|
|
78
|
+
|
|
79
|
+
return entry if result else None
|
|
80
|
+
|
|
81
|
+
def __init__(
|
|
82
|
+
self,
|
|
83
|
+
entity_id: Identity = SetmanId(Identity.auto().values),
|
|
84
|
+
name: str = None,
|
|
85
|
+
value: Any | None = None,
|
|
86
|
+
stype: SettingsType = None,
|
|
87
|
+
modified: str = now(),
|
|
88
|
+
):
|
|
89
|
+
super().__init__(entity_id)
|
|
90
|
+
self.name = name
|
|
91
|
+
self.value = value
|
|
92
|
+
self.stype = stype.val if stype else SettingsType.PROPERTY.val
|
|
93
|
+
self.modified = modified
|
|
94
|
+
|
|
95
|
+
def __str__(self) -> str:
|
|
96
|
+
return str(self.as_dict())
|
|
97
|
+
|
|
98
|
+
def __repr__(self) -> str:
|
|
99
|
+
return str(self)
|
|
100
|
+
|
|
101
|
+
def to_string(self, simple: bool = False) -> str:
|
|
102
|
+
"""Return the string representation of this entry.
|
|
103
|
+
"""
|
|
104
|
+
if simple:
|
|
105
|
+
return self._SIMPLE_FORMAT.format(environ_name(self.name), self.value) \
|
|
106
|
+
if self.stype == SettingsType.ENVIRONMENT.val \
|
|
107
|
+
else self._SIMPLE_FORMAT.format(self.name, self.value)
|
|
108
|
+
else:
|
|
109
|
+
return self._DISPLAY_FORMAT.format(self.name, self.stype, self.value, self.modified)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
@project: HsPyLib-Clitt
|
|
6
|
+
@package: clitt.addons.setman
|
|
7
|
+
@file: setman_enums.py
|
|
8
|
+
@created: Fri, 29 May 2023
|
|
9
|
+
@author: "<B>H</B>ugo <B>S</B>aporetti <B>J</B>unior")"
|
|
10
|
+
@site: "https://github.com/yorevs/hspylib")
|
|
11
|
+
@license: MIT - Please refer to <https://opensource.org/licenses/MIT>
|
|
12
|
+
|
|
13
|
+
Copyright 2023, HsPyLib team
|
|
14
|
+
"""
|
|
15
|
+
from typing import List
|
|
16
|
+
|
|
17
|
+
from hspylib.core.enums.enumeration import Enumeration
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SetmanOps(Enumeration):
|
|
21
|
+
"""Setman operations."""
|
|
22
|
+
|
|
23
|
+
# fmt: off
|
|
24
|
+
GET = 'get'
|
|
25
|
+
SET = 'set'
|
|
26
|
+
DEL = 'del'
|
|
27
|
+
LIST = 'list'
|
|
28
|
+
SEARCH = 'search'
|
|
29
|
+
TRUNCATE = 'truncate'
|
|
30
|
+
# fmt: on
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def choices() -> List[str]:
|
|
34
|
+
return SetmanOps.values()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class SettingsType(Enumeration):
|
|
38
|
+
"""Settings types."""
|
|
39
|
+
|
|
40
|
+
# fmt: off
|
|
41
|
+
ENVIRONMENT = 'environment'
|
|
42
|
+
PROPERTY = 'property'
|
|
43
|
+
# fmt: on
|
|
44
|
+
|
|
45
|
+
@staticmethod
|
|
46
|
+
def choices() -> List[str]:
|
|
47
|
+
return SettingsType.values()
|
|
48
|
+
|
|
49
|
+
@staticmethod
|
|
50
|
+
def selectables(selected: str = None) -> str:
|
|
51
|
+
return '|'.join([s if not s or s != selected else f"<{s}>" for s in SettingsType.values()])
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def val(self) -> str:
|
|
55
|
+
return str(self.value)
|