ttykit 0.2.2__tar.gz → 0.3.0b4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ttykit
3
- Version: 0.2.2
3
+ Version: 0.3.0b4
4
4
  Summary: Helping made beatiful out in terminal
5
5
  Author: He-STALIN
6
6
  Author-email: hene.stalin@gmail.com
@@ -47,18 +47,23 @@ Dynamic: license-file
47
47
  [![Repository](https://img.shields.io/badge/Repository-GitHub-4b93ff?style=flat&logo=github&logoColor=white)](https://github.com/He-STALIN/ttykit)
48
48
 
49
49
  </div>
50
+
50
51
  ---
51
52
 
52
53
  ## 📦 For Start
54
+ ### Manually:
53
55
 
54
56
  ```bash
55
57
  git clone https://github.com/He-STALIN/ttykit.git
56
58
  ```
57
59
 
58
60
  - Change dir and exec
61
+
59
62
  ```bash
60
63
  pip install .
61
64
  ```
65
+ ### Auto
66
+ - exec `pip install ttykit`
62
67
 
63
68
  - And use in your projects!
64
69
 
@@ -9,18 +9,23 @@
9
9
  [![Repository](https://img.shields.io/badge/Repository-GitHub-4b93ff?style=flat&logo=github&logoColor=white)](https://github.com/He-STALIN/ttykit)
10
10
 
11
11
  </div>
12
+
12
13
  ---
13
14
 
14
15
  ## 📦 For Start
16
+ ### Manually:
15
17
 
16
18
  ```bash
17
19
  git clone https://github.com/He-STALIN/ttykit.git
18
20
  ```
19
21
 
20
22
  - Change dir and exec
23
+
21
24
  ```bash
22
25
  pip install .
23
26
  ```
27
+ ### Auto
28
+ - exec `pip install ttykit`
24
29
 
25
30
  - And use in your projects!
26
31
 
@@ -8,7 +8,7 @@ include = ["ttykit*"]
8
8
 
9
9
  [project]
10
10
  name = "ttykit"
11
- version = "0.2.2"
11
+ version = "0.3.0b4"
12
12
  description = "Helping made beatiful out in terminal"
13
13
  requires-python = ">=3.13"
14
14
  authors = [
@@ -0,0 +1,67 @@
1
+ """Helping made beatiful out in terminal"""
2
+
3
+ from .progress import Progress
4
+ from .status import Status
5
+ from ._state import TaskState, Colors, Styles, RESET
6
+ from .console.console import Console
7
+ import traceback
8
+ import sys
9
+
10
+ __colors__ = [
11
+ Colors,
12
+ Styles,
13
+ RESET
14
+ ]
15
+
16
+ __all__ = [
17
+ 'Progress',
18
+ 'Status',
19
+ 'TaskState',
20
+ 'Console',
21
+ 'get_console',
22
+ 'set_custom_hook'
23
+ ]
24
+
25
+ def get_console() -> 'Console':
26
+ """Return a instance of `Console`"""
27
+ console = Console()
28
+ return console
29
+
30
+ def custom_excepthook(exc_type, exc_value, exc_tb):
31
+ tb_lines = traceback.format_exception(exc_type, exc_value, exc_tb)
32
+
33
+ # Самая длинная строка
34
+ error_line = f"Error: {exc_type.__name__}"
35
+ msg_line = f"Message: {exc_value}"
36
+ max_len = max(len(error_line), len(msg_line), 40)
37
+
38
+ # Рамка
39
+ print(f"╔{'═' * (max_len + 4)}╗")
40
+ print(f"║ {Colors.RED}{error_line.ljust(max_len)}{RESET} ║")
41
+ print(f"║ {Colors.RED}{msg_line.ljust(max_len)}{RESET} ║")
42
+ print(f"╠{'═' * (max_len + 4)}╣")
43
+
44
+ for line in tb_lines[-3:]:
45
+ clean = line.strip()
46
+ if len(clean) > max_len:
47
+ clean = clean[:max_len-3] + "..."
48
+ print(f"║ {clean.ljust(max_len)} ║")
49
+
50
+ print(f"╚{'═' * (max_len + 4)}╝")
51
+
52
+ def set_custom_hook(Traceback: bool= False) -> None:
53
+ """
54
+ Set a custom methods
55
+
56
+ Args:
57
+ Traceback (bool): replace Traceback on custom or not. Default `False`
58
+ """
59
+
60
+ if Traceback:
61
+ print('set custom excepthook...')
62
+ sys.excepthook = custom_excepthook
63
+
64
+ __name__ = 'ttykit'
65
+ __author__ = 'He-STALIN'
66
+ __version__ = '0.3.0b4'
67
+ __license__ = 'MIT'
@@ -0,0 +1,235 @@
1
+ import sys
2
+ import os
3
+ from typing import Optional, Literal, Mapping, Any
4
+ from ttykit import Colors, Styles
5
+
6
+ from .const import ColorSystem, WINDOWS
7
+
8
+ class Console:
9
+ """
10
+ Class for controling terminal events
11
+
12
+ Args:
13
+ color_system (str, Optional): Color system of the terminal. Either `standard`, `256` or `truecolor`. Leave as `auto` to autodetect.
14
+ width (int): width of the terminal. If state is `None`, calculates it automatically.
15
+ height (int): height of the terminal. If state is `None`, calculates it automatically.
16
+ stderr (bool): use `stderr` for errors instead of stdout. Default `False`.
17
+ no_color (bool): if `True`, the terminal be without colors, only monochrome (white and black). Default `False`.
18
+ force_terminal (bool): if `True` use terminal control codes in any situation.
19
+ """
20
+
21
+ _environ: Mapping[str, str] = os.environ
22
+
23
+ def __init__(self,
24
+ color_system: Optional[Literal["auto", "standard", "256", "truecolor", "windows"]] = "auto",
25
+ width: int = None,
26
+ height: int = None,
27
+ stderr: bool = False,
28
+ no_color: bool = False,
29
+ force_terminal: Optional[bool] = False
30
+ ):
31
+ super().__init__()
32
+
33
+ #? preparing to avoid any errors
34
+ self._color_system = Optional[ColorSystem]
35
+ self._force_terminal = None
36
+ self.stderr = stderr
37
+ self.no_color = no_color
38
+ self.height = None
39
+ self.width = None
40
+
41
+ if color_system is None:
42
+ self._color_system = None
43
+ elif color_system == "auto":
44
+ self._color_system = self._detect_colorSystem()
45
+
46
+ if force_terminal is not None:
47
+ self._force_terminal = force_terminal
48
+
49
+ if width is None:
50
+ try:
51
+ size = os.get_terminal_size()
52
+ width = size.columns
53
+ except OSError:
54
+ print('Error calculating width of the terminal. Use default value (80)')
55
+ width = 80
56
+
57
+ if height is None:
58
+ try:
59
+ size = os.get_terminal_size()
60
+ height = size.lines
61
+ except OSError:
62
+ print('Error calculating height of the terminal. Use default value (24)')
63
+ height
64
+
65
+ def _print_error(self, msg: str=None):
66
+ if msg is None:
67
+ return
68
+
69
+ if self.stderr:
70
+ sys.stderr.write(msg)
71
+
72
+ @property
73
+ def isTerminal(self) -> bool:
74
+ """
75
+ Check if the console writing to a terminal
76
+
77
+ Returns:
78
+ state (bool): return `True` if console is understanding escape sequences, otherwise `False`
79
+ """
80
+ if self._force_terminal is not None:
81
+ return True
82
+
83
+ if hasattr(sys.stdin, "__module__") and sys.stdin.__module__.startswith("idlelib"):
84
+ return False #? return False for idle which claims to be a tty but can't handle ANSI codes
85
+
86
+ ttyCompatyble = self._environ.get('TTY_COMPATIBLE', '')
87
+ if ttyCompatyble == '0': #? 0 = device is not tty compatible
88
+ return False
89
+ elif ttyCompatyble =='1': #? 1 = device is tty compatible
90
+ return True
91
+
92
+ if not sys.stdout.isatty():
93
+ return False
94
+
95
+
96
+ @property
97
+ def is_dumb_terminal(self) -> bool:
98
+ """Detect dumb terminal.
99
+
100
+ Returns:
101
+ state (bool): `True` if writing to a dumb terminal, otherwise `False`.
102
+
103
+ """
104
+ is_dumb = self._environ.get("TERM", "").lower() in ("dumb", "unknown")
105
+ return self.isTerminal and is_dumb
106
+
107
+
108
+ @property
109
+ def color_system(self):
110
+ return self._detect_colorSystem()
111
+
112
+
113
+ def _detect_colorSystem(self) -> Optional[ColorSystem]:
114
+ """Autodetect the supported color theme fo the terminal"""
115
+
116
+ if self.no_color:
117
+ return None
118
+
119
+ if WINDOWS:
120
+ # TODO: add check for legacy windows
121
+
122
+ if self._environ.get('COLORTERM') in ('truecolor', '24bit'):
123
+ return ColorSystem.TRUECOLOR
124
+ return ColorSystem.WINDOWS
125
+ else:
126
+ if self._environ.get('COLORTERM') in ('truecolor', '24bit'):
127
+ return ColorSystem.TRUECOLOR
128
+
129
+ if self._environ.get("TERM") in ("xterm-256color", "screen-256color"):
130
+ return ColorSystem.EIGHT_BIT
131
+ return ColorSystem.STANDARD
132
+
133
+ def _get_style_code(self, style: str) -> str:
134
+ styles = {
135
+ 'bold': Styles.BOLD,
136
+ 'dim': Styles.DIM,
137
+ 'italic': Styles.ITALIC,
138
+ 'underline': Styles.UNDERLINE,
139
+ 'blink': Styles.BLINK,
140
+ 'rapid_blink': Styles.RAPID_BLINK,
141
+ 'reverse': Styles.REVERSE
142
+ }
143
+ return styles.get(style, '')
144
+
145
+ def _get_color_code(self, color: str) -> str:
146
+ colors = {
147
+ "black": Colors.BLACK,
148
+ "red": Colors.RED,
149
+ "green": Colors.GREEN,
150
+ "yellow": Colors.YELLOW,
151
+ "blue": Colors.BLUE,
152
+ "purple": Colors.PURPLE,
153
+ "cyan": Colors.CYAN,
154
+ "white": Colors.WHITE,
155
+ "dark_grey": Colors.DARK_GREY,
156
+ "light_red": Colors.LIGHT_RED,
157
+ "light_green": Colors.LIGHT_GREEN,
158
+ "light_yellow": Colors.LIGHT_YELLOW,
159
+ "light_blue": Colors.LIGHT_BLUE,
160
+ "light_purple": Colors.LIGHT_PURPLE,
161
+ "light_cyan": Colors.LIGHT_CYAN,
162
+ "light_white": Colors.LIGHT_WHITE
163
+ }
164
+ return colors.get(color, "")
165
+
166
+ def bell(self):
167
+ sys.stdout.write("\a")
168
+ sys.stdout.flush()
169
+
170
+ def print(self,
171
+ *args,
172
+ sep: str | None=" ",
173
+ end: str | None ="\n",
174
+ style: str | None=None,
175
+ color: str | None=None) -> None:
176
+ """
177
+ Print the args to a stream
178
+
179
+ Args:
180
+ *args (Any): args to write to a stream
181
+ sep (str | None): string inserted between values, default a space.
182
+ end (str | None): string appended after the last value, default a newline.
183
+ style: style of args write to a steam, default `None`.
184
+ color: color of args write to a stream, default `None`.
185
+ Returns:
186
+ None: write in `stdout`
187
+ """
188
+ if not self.isTerminal or self.no_color:
189
+ #? Just out, without colors or styles
190
+ sys.stdout.write(sep.join(str(a) for a in args) + end)
191
+ return
192
+
193
+ #TODO: realize print logic with color style replace
194
+
195
+ #? Apply the style with color to args
196
+ text = sep.join(str(a) for a in args)
197
+ if color and self.color_system:
198
+ color_code = self._get_color_code(color.lower())
199
+ text = f"{color_code}{text}{Colors.RESET}"
200
+
201
+ if style:
202
+ style_code = self._get_style_code(style.lower())
203
+ text = f"{style_code}{text}"
204
+
205
+ sys.stdout.write(text + end)
206
+ sys.stdout.flush()
207
+
208
+
209
+ def input(self,
210
+ prompt = '',
211
+ *,
212
+ style: str | None = None,
213
+ color: str | None = None,
214
+ password: bool = False) -> str:
215
+ """
216
+ Displays a prompt if have and waits for input from user.
217
+
218
+ Args:
219
+ prompt: text to render in prompt
220
+ style (str | None): style for prompt render. Required prompt
221
+ color (str | None): color for prompt render. Required prompt
222
+ password (bool): if `True`, hide typed text. Default `False`
223
+ Returns:
224
+ result (str): typed text from user from stdin
225
+ """
226
+
227
+ if prompt:
228
+ self.print(prompt, style=style, color=color, end='')
229
+
230
+ if password:
231
+ # TODO: realize text hidding
232
+ Warning("This attribute in developing. Please, set 'password=False'")
233
+ else:
234
+ result = input()
235
+ return result
@@ -0,0 +1,18 @@
1
+ from enum import IntEnum
2
+ import sys
3
+
4
+ WINDOWS = sys.platform == "win32"
5
+
6
+ class ColorSystem(IntEnum):
7
+ """One of the 3 color system supported by terminals."""
8
+
9
+ STANDARD = 1
10
+ EIGHT_BIT = 2
11
+ TRUECOLOR = 3
12
+ WINDOWS = 4
13
+
14
+ def __repr__(self) -> str:
15
+ return f"ColorSystem.{self.name}"
16
+
17
+ def __str__(self) -> str:
18
+ return repr(self)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ttykit
3
- Version: 0.2.2
3
+ Version: 0.3.0b4
4
4
  Summary: Helping made beatiful out in terminal
5
5
  Author: He-STALIN
6
6
  Author-email: hene.stalin@gmail.com
@@ -47,18 +47,23 @@ Dynamic: license-file
47
47
  [![Repository](https://img.shields.io/badge/Repository-GitHub-4b93ff?style=flat&logo=github&logoColor=white)](https://github.com/He-STALIN/ttykit)
48
48
 
49
49
  </div>
50
+
50
51
  ---
51
52
 
52
53
  ## 📦 For Start
54
+ ### Manually:
53
55
 
54
56
  ```bash
55
57
  git clone https://github.com/He-STALIN/ttykit.git
56
58
  ```
57
59
 
58
60
  - Change dir and exec
61
+
59
62
  ```bash
60
63
  pip install .
61
64
  ```
65
+ ### Auto
66
+ - exec `pip install ttykit`
62
67
 
63
68
  - And use in your projects!
64
69
 
@@ -11,4 +11,6 @@ src/ttykit.egg-info/SOURCES.txt
11
11
  src/ttykit.egg-info/dependency_links.txt
12
12
  src/ttykit.egg-info/entry_points.txt
13
13
  src/ttykit.egg-info/requires.txt
14
- src/ttykit.egg-info/top_level.txt
14
+ src/ttykit.egg-info/top_level.txt
15
+ src/ttykit/console/console.py
16
+ src/ttykit/console/const.py
@@ -1,22 +0,0 @@
1
- """Helping made beatiful out in terminal"""
2
-
3
- from .progress import Progress
4
- from .status import Status
5
- from ._state import TaskState, Colors, Styles, RESET
6
-
7
- __colors__ = [
8
- Colors,
9
- Styles,
10
- RESET
11
- ]
12
-
13
- __all__ = [
14
- 'Progress',
15
- 'Status',
16
- 'TaskState'
17
- ]
18
-
19
- __name__ = 'ttykit'
20
- __author__ = 'He-STALIN'
21
- __version__ = '0.2.2'
22
- __license__ = 'MIT'
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes