hspylib-clitt 0.9.41__py3-none-any.whl → 0.9.51__py3-none-any.whl

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.

Files changed (60) hide show
  1. clitt/.version +1 -1
  2. clitt/__classpath__.py +1 -1
  3. clitt/__init__.py +4 -3
  4. clitt/__main__.py +8 -41
  5. clitt/addons/__init__.py +2 -3
  6. clitt/addons/appman/__init__.py +2 -2
  7. clitt/addons/appman/appman.py +1 -1
  8. clitt/addons/appman/templates/__init__.py +2 -2
  9. clitt/addons/widman/__init__.py +2 -2
  10. clitt/addons/widman/widgets/__init__.py +2 -2
  11. clitt/addons/widman/widgets/widget_free.py +2 -1
  12. clitt/addons/widman/widgets/widget_punch.py +3 -2
  13. clitt/core/__init__.py +3 -3
  14. clitt/core/icons/__init__.py +2 -2
  15. clitt/core/icons/emojis/__init__.py +2 -2
  16. clitt/core/icons/font_awesome/__init__.py +2 -2
  17. clitt/core/term/__init__.py +14 -0
  18. clitt/core/term/commons.py +63 -0
  19. clitt/core/term/cursor.py +124 -0
  20. clitt/core/term/screen.py +96 -0
  21. clitt/core/term/terminal.py +173 -0
  22. clitt/core/tui/__init__.py +3 -4
  23. clitt/core/tui/mchoose/__init__.py +2 -2
  24. clitt/core/tui/mchoose/menu_choose.py +6 -5
  25. clitt/core/tui/mdashboard/__init__.py +2 -2
  26. clitt/core/tui/mdashboard/menu_dashboard.py +9 -9
  27. clitt/core/tui/menu/__init__.py +2 -2
  28. clitt/core/tui/menu/tui_menu_action.py +1 -3
  29. clitt/core/tui/menu/tui_menu_item.py +6 -5
  30. clitt/core/tui/menu/tui_menu_ui.py +5 -7
  31. clitt/core/tui/menu/tui_menu_view.py +2 -3
  32. clitt/core/tui/minput/__init__.py +2 -2
  33. clitt/core/tui/minput/menu_input.py +22 -18
  34. clitt/core/tui/minput/minput_utils.py +4 -3
  35. clitt/core/tui/mselect/__init__.py +2 -2
  36. clitt/core/tui/mselect/menu_select.py +6 -5
  37. clitt/core/tui/table/__init__.py +2 -2
  38. clitt/core/tui/table/table_renderer.py +13 -15
  39. clitt/core/tui/tui_application.py +27 -13
  40. clitt/core/tui/tui_component.py +28 -21
  41. clitt/core/tui/tui_preferences.py +3 -0
  42. clitt/utils/__init__.py +11 -0
  43. clitt/utils/git_utils.py +67 -0
  44. clitt/welcome.txt +6 -6
  45. {hspylib_clitt-0.9.41.dist-info → hspylib_clitt-0.9.51.dist-info}/METADATA +4 -4
  46. hspylib_clitt-0.9.51.dist-info/RECORD +90 -0
  47. clitt/addons/setman/__init__.py +0 -13
  48. clitt/addons/setman/setman.py +0 -148
  49. clitt/addons/setman/setman_config.py +0 -26
  50. clitt/addons/setman/setman_enums.py +0 -54
  51. clitt/core/settings/__init__.py +0 -15
  52. clitt/core/settings/settings.py +0 -182
  53. clitt/core/settings/settings_config.py +0 -47
  54. clitt/core/settings/settings_entry.py +0 -108
  55. clitt/core/settings/settings_repository.py +0 -103
  56. clitt/core/settings/settings_service.py +0 -50
  57. clitt/core/tui/tui_screen.py +0 -222
  58. hspylib_clitt-0.9.41.dist-info/RECORD +0 -94
  59. {hspylib_clitt-0.9.41.dist-info → hspylib_clitt-0.9.51.dist-info}/WHEEL +0 -0
  60. {hspylib_clitt-0.9.41.dist-info → hspylib_clitt-0.9.51.dist-info}/top_level.txt +0 -0
@@ -1,54 +0,0 @@
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 hspylib.core.enums.enumeration import Enumeration
16
- from typing import List
17
-
18
-
19
- class SetmanOps(Enumeration):
20
- """Setman operations."""
21
-
22
- # fmt: off
23
- GET = 'get'
24
- SET = 'set'
25
- DEL = 'del'
26
- LIST = 'list'
27
- SEARCH = 'search'
28
- TRUNCATE = 'truncate'
29
- # fmt: on
30
-
31
- @staticmethod
32
- def choices() -> List[str]:
33
- return SetmanOps.values()
34
-
35
-
36
- class SettingsType(Enumeration):
37
- """Settings types."""
38
-
39
- # fmt: off
40
- ENVIRONMENT = 'environment'
41
- PROPERTY = 'property'
42
- # fmt: on
43
-
44
- @staticmethod
45
- def choices() -> List[str]:
46
- return SettingsType.values()
47
-
48
- @staticmethod
49
- def selectables(selected: str = None) -> str:
50
- return "|".join([s if not s or s != selected else f"<{s}>" for s in SettingsType.values()])
51
-
52
- @property
53
- def val(self) -> str:
54
- return str(self.value)
@@ -1,15 +0,0 @@
1
- # _*_ coding: utf-8 _*_
2
- #
3
- # hspylib-clitt v0.9.41
4
- #
5
- # Package: main.clitt.core.settings
6
- """Package initialization."""
7
-
8
- __all__ = [
9
- 'settings',
10
- 'settings_config',
11
- 'settings_entry',
12
- 'settings_repository',
13
- 'settings_service'
14
- ]
15
- __version__ = '0.9.41'
@@ -1,182 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
- """
5
- @project: HsPyLib
6
- @package: clitt.addons.setman
7
- @file: settings.py
8
- @created: Thu, 04 Jul 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 binascii
16
- import contextlib
17
- import logging as log
18
- import os
19
- import uuid
20
- from typing import Any, List, Optional, Tuple
21
-
22
- from datasource.identity import Identity
23
- from hspylib.core.exception.exceptions import ApplicationError
24
- from hspylib.core.preconditions import check_state
25
- from hspylib.core.tools.commons import file_is_not_empty, safe_delete_file, touch_file
26
- from hspylib.core.zoned_datetime import now
27
- from hspylib.modules.security.security import decode_file, encode_file
28
-
29
- from clitt.addons.setman.setman_enums import SettingsType
30
- from clitt.core.settings.settings_config import SettingsConfig
31
- from clitt.core.settings.settings_entry import SettingsEntry
32
- from clitt.core.settings.settings_service import SettingsService
33
-
34
-
35
- class Settings:
36
- """Class to provide settings interactions."""
37
-
38
- def __init__(self, configs: SettingsConfig) -> None:
39
- self._is_open = False
40
- self._configs = configs
41
- self._service = SettingsService(self.configs)
42
- if not file_is_not_empty(self.configs.database):
43
- self._create_db()
44
-
45
- def __str__(self):
46
- entries = f",{os.linesep} ".join(list(map(lambda s: str(s), self.list())))
47
- return (
48
- f"Settings: [{os.linesep + ' ' if entries else ''}"
49
- f"{entries}"
50
- f"{os.linesep if entries else ''}]"
51
- )
52
-
53
- def __repr__(self):
54
- return str(self)
55
-
56
- def __getitem__(self, name: str) -> SettingsEntry:
57
- return self.get(name)
58
-
59
- def __setitem__(self, name: str, item: Tuple[Any, SettingsType]) -> None:
60
- self.upsert(name, item[0], item[1])
61
-
62
- @property
63
- def configs(self) -> SettingsConfig:
64
- return self._configs
65
-
66
- @property
67
- def is_open(self) -> bool:
68
- return self._is_open
69
-
70
- @is_open.setter
71
- def is_open(self, new_is_open: bool) -> None:
72
- self._is_open = new_is_open
73
- log.debug(f"Settings database open: {self.configs.database}")
74
-
75
- @contextlib.contextmanager
76
- def open(self) -> None:
77
- """Decode and open the SQL lite database file. Return the context to manipulate it."""
78
- try:
79
- if not self.is_open:
80
- self.is_open = True
81
- if self.configs.is_db_encoded:
82
- self._decode_db_file()
83
- yield self
84
- except (UnicodeDecodeError, binascii.Error) as err:
85
- err_msg = f"Failed to open settings file => {self.configs.database}"
86
- log.error(ApplicationError(err_msg, err))
87
- except Exception as err:
88
- err_msg = f"Unable to close settings file => {self.configs.database}"
89
- raise ApplicationError(err_msg, err) from err
90
- finally:
91
- self.close()
92
-
93
- def close(self) -> None:
94
- """Encode and open the SQL lite database file. Return the context to manipulate it."""
95
- try:
96
- if self._is_open:
97
- if self.configs.is_db_encoded:
98
- self._encode_db_file()
99
- self._is_open = False
100
- log.debug(f"Settings database closed: {self.configs.database}")
101
- except (UnicodeDecodeError, binascii.Error) as err:
102
- err_msg = f"Failed to close settings file => {self.configs.database}"
103
- raise ApplicationError(err_msg, err) from err
104
- except Exception as err:
105
- err_msg = f"Unable to close settings file => {self.configs.database}"
106
- raise ApplicationError(err_msg, err) from err
107
- finally:
108
- safe_delete_file(self.configs.encoded_db)
109
- safe_delete_file(self.configs.decoded_db)
110
-
111
- def list(self) -> List[SettingsEntry]:
112
- """List all database settings using as a formatted table."""
113
- check_state(self.is_open, "Settings database is not open")
114
- return self._service.list()
115
-
116
- def search(self, name: str, stype: SettingsType, simple_fmt: bool) -> List[str]:
117
- """Display all settings matching the name and settings type."""
118
- check_state(self.is_open, "Settings database is not open")
119
- return list(map(lambda e: e.to_string(simple_fmt), self._service.search(name, stype)))
120
-
121
- def remove(self, name: str) -> Optional[SettingsEntry]:
122
- """Delete the specified setting."""
123
- check_state(self.is_open, "Settings database is not open")
124
- if name:
125
- found = self._service.get(name)
126
- if found:
127
- self._service.remove(found)
128
- return found
129
- return None
130
-
131
- def get(self, name: str) -> Optional[SettingsEntry]:
132
- """Get the specified setting."""
133
- check_state(self.is_open, "Settings database is not open")
134
- if name:
135
- return self._service.get(name)
136
- return None
137
-
138
- def upsert(
139
- self,
140
- name: str,
141
- value: Any,
142
- stype: SettingsType) -> Tuple[Optional[SettingsEntry], Optional[SettingsEntry]]:
143
- """Upsert the specified setting."""
144
-
145
- check_state(self.is_open, "Settings database is not open")
146
- found = self._service.get(name)
147
- entry = found or SettingsEntry(Identity(SettingsEntry.SetmanId(uuid.uuid4().hex)), name, value, stype)
148
- if not name or value is None or not stype:
149
- entry = SettingsEntry.prompt(entry)
150
- if entry:
151
- entry.modified = now()
152
- self._service.save(entry)
153
- return found, entry
154
-
155
- def clear(self) -> None:
156
- """Clear all settings from the settings table."""
157
- check_state(self.is_open, "Settings database is not open")
158
- self._service.clear()
159
-
160
- def _create_db(self) -> bool:
161
- """Create the settings SQLite DB file."""
162
- touch_file(self.configs.database)
163
- self._service.create_db()
164
- log.info("Settings file has been created")
165
- self._is_open = True
166
- return os.path.exists(self.configs.database)
167
-
168
- def _encode_db_file(self) -> None:
169
- """Decode the Base64 encoded database file."""
170
- if file_is_not_empty(self.configs.database):
171
- encoded = f"{self.configs.database}-encoded"
172
- encode_file(self.configs.database, encoded, binary=True)
173
- os.rename(encoded, self.configs.database)
174
- log.debug("Settings file is encoded")
175
-
176
- def _decode_db_file(self) -> None:
177
- """Base64 encode the database file."""
178
- if file_is_not_empty(self.configs.database):
179
- decoded = f"{self.configs.database}-decoded"
180
- decode_file(self.configs.database, decoded, binary=True)
181
- os.rename(decoded, self.configs.database)
182
- log.debug("Settings file is decoded")
@@ -1,47 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
- """
5
- @project: HsPyLib-Clitt
6
- @package: clitt.addons.setman
7
- @file: settings_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
- from hspylib.core.tools.commons import str_to_bool
17
-
18
-
19
- class SettingsConfig(DBConfiguration):
20
- """Holds the settings configurations."""
21
-
22
- INSTANCE = None
23
-
24
- def __init__(self, resource_dir: str, filename: str):
25
- super().__init__(resource_dir, filename)
26
- self._database: str = self["hhs.settings.database"]
27
- self._encode_db: bool = str_to_bool(self["hhs.settings.encode.database"])
28
-
29
- @property
30
- def database(self) -> str:
31
- """Return the settings database name."""
32
- return self._database
33
-
34
- @property
35
- def is_db_encoded(self) -> bool:
36
- """Return the settings encode database."""
37
- return self._encode_db
38
-
39
- @property
40
- def encoded_db(self) -> str:
41
- """Return the settings encoded-database name."""
42
- return f"{self.database}-encoded"
43
-
44
- @property
45
- def decoded_db(self) -> str:
46
- """Return the settings decoded-database name."""
47
- return f"{self.database}-decoded"
@@ -1,108 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
- """
5
- @project: HsPyLib-Clitt
6
- @package: clitt.addons.setman
7
- @file: settings_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 clitt.addons.setman.setman_enums import SettingsType
16
- from clitt.core.tui.minput.menu_input import MenuInput
17
- from clitt.core.tui.minput.minput import minput
18
- from collections import namedtuple
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
- from textwrap import dedent
24
- from typing import Any, Optional, Union
25
-
26
-
27
- class SettingsEntry(CrudEntity):
28
- """Represents the Settings domain object."""
29
-
30
- SetmanId = namedtuple("SetmanId", ["uuid"])
31
-
32
- # Setman entry display format.
33
- _DISPLAY_FORMAT = dedent(
34
- """
35
- [%BLUE%{}%NC%]:
36
- Type: %GREEN%{}%NC%
37
- Value: %GREEN%{}%NC%
38
- Modified: %GREEN%{}%NC%
39
- """
40
- )
41
-
42
- # Setman entry simple format.
43
- _SIMPLE_FORMAT = "{}={}"
44
-
45
- @staticmethod
46
- def prompt(entry: Union["SettingsEntry", None] = None) -> Optional["SettingsEntry"]:
47
- """Create a settings entry from a form input."""
48
-
49
- entry = entry or SettingsEntry()
50
- # fmt: off
51
- form_fields = MenuInput.builder() \
52
- .field() \
53
- .label('Name') \
54
- .min_max_length(1, 60) \
55
- .value(entry.name) \
56
- .build() \
57
- .field() \
58
- .label('Value') \
59
- .min_max_length(1, 60) \
60
- .value(entry.value) \
61
- .build() \
62
- .field() \
63
- .label('Type') \
64
- .itype('select') \
65
- .dest('stype') \
66
- .value(SettingsType.selectables(entry.stype) if entry.stype else None) \
67
- .build() \
68
- .build()
69
- # fmt: on
70
-
71
- if result := minput(form_fields, "Please fill the settings details"):
72
- entry.name = result.name
73
- entry.value = result.value
74
- entry.stype = result.stype
75
- entry.modified = now()
76
-
77
- return entry if result else None
78
-
79
- def __init__(
80
- self,
81
- entity_id: Identity = SetmanId(Identity.auto().values),
82
- name: str = None,
83
- value: Any | None = None,
84
- stype: SettingsType = None,
85
- modified: str = now(),
86
- ):
87
- super().__init__(entity_id)
88
- self.name: str = name
89
- self.value: Any = value
90
- self.stype: str = stype.val if stype else SettingsType.PROPERTY.val
91
- self.modified: str = modified
92
-
93
- def __str__(self) -> str:
94
- return str(self.as_dict())
95
-
96
- def __repr__(self) -> str:
97
- return self.to_string()
98
-
99
- def to_string(self, simple: bool = False) -> str:
100
- """Return the string representation of this entry."""
101
- if simple:
102
- return (
103
- self._SIMPLE_FORMAT.format(environ_name(self.name), self.value)
104
- if self.stype == SettingsType.ENVIRONMENT.val
105
- else self._SIMPLE_FORMAT.format(self.name, self.value)
106
- )
107
- else:
108
- return self._DISPLAY_FORMAT.format(self.name, self.stype, self.value, self.modified)
@@ -1,103 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
- """
5
- @project: HsPyLib-Clitt
6
- @package: clitt.addons.setman
7
- @file: settings_repository.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 clitt.addons.setman.setman_enums import SettingsType
16
- from datasource.identity import Identity
17
- from datasource.sqlite.sqlite_repository import SQLiteRepository
18
- from textwrap import dedent
19
- from typing import List, Optional
20
-
21
- from clitt.core.settings.settings_entry import SettingsEntry
22
-
23
-
24
- class SettingsRepository(SQLiteRepository[SettingsEntry]):
25
- """Provide CRUD operations for the Settings."""
26
-
27
- @property
28
- def database(self) -> str:
29
- return self._config.database
30
-
31
- def find_by_name(self, name: str) -> Optional[SettingsEntry]:
32
- """Find settings by name."""
33
- sql = f"SELECT * FROM SETTINGS WHERE name = ? ORDER BY name"
34
- result = next((e for e in self.execute(sql, name=name)[1]), None)
35
-
36
- return self.to_entity_type(result) if result else None
37
-
38
- def search(self, name: str, stype: SettingsType) -> List[SettingsEntry]:
39
- """Search settings by settings type."""
40
- search_name = name.replace("*", "%") if name else "%"
41
- if stype:
42
- sql = "SELECT * FROM SETTINGS WHERE name LIKE ? AND stype = ? ORDER BY name"
43
- result = self.execute(sql, name=search_name, stype=stype.val)[1] or []
44
- else:
45
- sql = "SELECT * FROM SETTINGS WHERE name LIKE ? ORDER BY name"
46
- result = self.execute(sql, name=search_name)[1] or []
47
-
48
- return list(map(self.to_entity_type, result))
49
-
50
- def truncate(self) -> None:
51
- """TODO"""
52
- self.execute("DELETE FROM SETTINGS")
53
-
54
- def create_db(self) -> None:
55
- """TODO"""
56
- self.execute(
57
- dedent(
58
- """
59
- CREATE TABLE IF NOT EXISTS SETTINGS
60
- (
61
- uuid TEXT not null,
62
- name TEXT not null,
63
- value TEXT not null,
64
- stype TEXT not null,
65
- modified TEXT not null,
66
-
67
- CONSTRAINT UUID_pk PRIMARY KEY (uuid),
68
- CONSTRAINT NAME_uk UNIQUE (name)
69
- )
70
- """
71
- )
72
- )
73
- self.execute(
74
- dedent(
75
- """
76
- CREATE TABLE IF NOT EXISTS SETTINGS_EVENTS
77
- (
78
- uuid TEXT not null,
79
- event TEXT not null,
80
- name TEXT not null,
81
- old_value TEXT not null,
82
- new_value TEXT not null,
83
- created TEXT not null,
84
-
85
- CONSTRAINT UUID_pk PRIMARY KEY (uuid)
86
- )
87
- """
88
- )
89
- )
90
-
91
- def table_name(self) -> str:
92
- return "SETTINGS"
93
-
94
- def to_entity_type(self, entity_dict: dict | tuple) -> SettingsEntry:
95
- if isinstance(entity_dict, dict):
96
- return SettingsEntry(Identity(SettingsEntry.SetmanId(entity_dict["uuid"])), **entity_dict)
97
- return SettingsEntry(
98
- Identity(SettingsEntry.SetmanId(entity_dict[0])),
99
- entity_dict[1],
100
- entity_dict[2],
101
- SettingsType.of_value(entity_dict[3]),
102
- entity_dict[4],
103
- )
@@ -1,50 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
- """
5
- @project: HsPyLib-Clitt
6
- @package: clitt.addons.setman
7
- @file: settings_service.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 typing import List, Optional
16
-
17
- from datasource.crud_service import CrudService
18
-
19
- from clitt.addons.setman.setman_enums import SettingsType
20
- from clitt.core.settings.settings_config import SettingsConfig
21
- from clitt.core.settings.settings_entry import SettingsEntry
22
- from clitt.core.settings.settings_repository import SettingsRepository
23
-
24
-
25
- class SettingsService(CrudService[SettingsRepository, SettingsEntry]):
26
- """Provides a CRUD service for the Setman application."""
27
-
28
- def __init__(self, setman_config: SettingsConfig):
29
- super().__init__(SettingsRepository(setman_config))
30
-
31
- def get(self, name: str) -> Optional[SettingsEntry]:
32
- """Get a setman entry using the specified name.
33
- :param name: the setman entry name to find.
34
- """
35
- return self.repository.find_by_name(name)
36
-
37
- def search(self, name: str, stype: SettingsType = None) -> List[SettingsEntry]:
38
- """Get a setman entry using the specified name.
39
- :param name: the setman entry name to find.
40
- :param stype: the settings type to filter.
41
- """
42
- return self.repository.search(name, stype)
43
-
44
- def clear(self) -> None:
45
- """Clear all settings from the settings table."""
46
- self.repository.truncate()
47
-
48
- def create_db(self) -> None:
49
- """Create a brand new setman database file."""
50
- self.repository.create_db()