oakley 2.1.10__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.
oakley-2.1.10/LICENCE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2018 The Python Packaging Authority
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
oakley-2.1.10/PKG-INFO ADDED
@@ -0,0 +1,125 @@
1
+ Metadata-Version: 2.4
2
+ Name: oakley
3
+ Version: 2.1.10
4
+ Summary: A small collection of lightweight, opinionated utilities for printing fancy console output in Python: colored strings, pretty messages, simple progress bars, task context managers, and tiny system/status helpers.
5
+ Author-email: Jonas Wehrung-Montpezat <kiwi.grodoudou@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/ProfesseurShadoko/oakley
8
+ Keywords: console,progress bar,utilities,colored output
9
+ Requires-Python: >=3.8
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENCE
12
+ Requires-Dist: psutil>=5.9
13
+ Dynamic: license-file
14
+
15
+
16
+ # oakley
17
+
18
+ A small collection of lightweight, opinionated utilities for printing "fancy" console output in Python: colored strings, pretty messages, simple progress bars, task context managers, and tiny system/status helpers.
19
+
20
+ This package is designed for developer convenience when running short scripts or CLI-style tasks. It provides a few cooperating classes that make it easy to print colored, indented, and optionally muted output, plus a couple of helpers for memory and time display.
21
+
22
+ ## Features
23
+
24
+ - Colored strings with convenient format specifiers (`cstr`) — easy ANSI coloring and simple format shortcuts.
25
+ - `Message` class for categorized, pretty messages (info, warning, error, success).
26
+ - `Task` context manager to wrap and time operations, with neat completion/abort output.
27
+ - `ProgressBar` iterator wrapper with estimated remaining time and non-intrusive whisper messages.
28
+ - `MutableClass` base with global mute/tab behavior so multiple components coordinate console output.
29
+ - Small status helpers: `MemoryView`, `TODO` and `DateTime` for quick runtime info.
30
+
31
+ ## Installation
32
+
33
+ You can downlaod the package with this command:
34
+ ```bash
35
+ pip install oakley
36
+ ```
37
+ Alternatively, you can download the most up-to-date version from my github repository:
38
+ ```bash
39
+ pip install git+https://github.com/ProfesseurShadoko/oakley.git
40
+ ```
41
+
42
+ ## Quick examples
43
+
44
+ Colored strings
45
+
46
+ ```python
47
+ from oakley import cstr
48
+ print(cstr('hello world').green().bold())
49
+ print(f"Progress: {cstr('ok'):g}") # short color spec
50
+ print(f"{cstr('Done'):gb}") # in green and bold
51
+ ```
52
+
53
+ Pretty messages
54
+
55
+ ```python
56
+ from oakley import Message
57
+ Message("Build succeeded", "#") # green success prefix
58
+ Message("Something might be wrong", "?")
59
+ ```
60
+
61
+ Tasks and timing
62
+
63
+ ```python
64
+ from oakley import Task
65
+ import time
66
+
67
+ with Task("Compute something heavy"):
68
+ time.sleep(1.2)
69
+
70
+ ```
71
+
72
+ Progress bar
73
+
74
+ ```python
75
+ from oakley import ProgressBar
76
+ import time
77
+
78
+ for i in ProgressBar(range(50), size=50):
79
+ time.sleep(0.02)
80
+ if i == 25:
81
+ ProgressBar.whisper("Halfway there!")
82
+ ```
83
+
84
+ Status helpers
85
+
86
+ ```python
87
+ from oakley import MemoryView, TODO
88
+ MemoryView() # prints a short memory usage line (requires psutil)
89
+ TODO("Refactor the parser")
90
+ ```
91
+
92
+ Mute and indentation
93
+
94
+ ```python
95
+ from oakley import MutableClass, Message
96
+
97
+ MutableClass.mute() # globally mute printing
98
+ MutableClass.unmute()
99
+
100
+ with Message.mute():
101
+ Message.print("This won't be printed")
102
+ Message.print("This will be printed again!")
103
+
104
+ with Message("The following messages will be indented"): # increase indentation for nested prints
105
+ Message.print("This will be indented")
106
+ MemoryView() # also indented
107
+ Message("This won't be indented")
108
+ ```
109
+
110
+ ## Examples
111
+
112
+ Take a look at [this notebook](https://github.com/ProfesseurShadoko/oakley/blob/main/example.ipynb) for the most detailed and up to date examples.
113
+
114
+ Alternatively, run the command:
115
+ ```bash
116
+ python -m oakley.<filename_without_dot_py>
117
+ ```
118
+ to see examples for each object.
119
+
120
+
121
+ ## Development notes
122
+
123
+ - The package is intentionally tiny and uses ANSI escape sequences for coloring; compatibility is best on UNIX-like terminals.
124
+ - `MemoryView` depends on `psutil` — the package runs fine even when `psutil` is not available, but the `MemoryView` object cannot be used.
125
+ - There are simple demo blocks in each module under `if __name__ == '__main__'` for manual testing.
@@ -0,0 +1,111 @@
1
+
2
+ # oakley
3
+
4
+ A small collection of lightweight, opinionated utilities for printing "fancy" console output in Python: colored strings, pretty messages, simple progress bars, task context managers, and tiny system/status helpers.
5
+
6
+ This package is designed for developer convenience when running short scripts or CLI-style tasks. It provides a few cooperating classes that make it easy to print colored, indented, and optionally muted output, plus a couple of helpers for memory and time display.
7
+
8
+ ## Features
9
+
10
+ - Colored strings with convenient format specifiers (`cstr`) — easy ANSI coloring and simple format shortcuts.
11
+ - `Message` class for categorized, pretty messages (info, warning, error, success).
12
+ - `Task` context manager to wrap and time operations, with neat completion/abort output.
13
+ - `ProgressBar` iterator wrapper with estimated remaining time and non-intrusive whisper messages.
14
+ - `MutableClass` base with global mute/tab behavior so multiple components coordinate console output.
15
+ - Small status helpers: `MemoryView`, `TODO` and `DateTime` for quick runtime info.
16
+
17
+ ## Installation
18
+
19
+ You can downlaod the package with this command:
20
+ ```bash
21
+ pip install oakley
22
+ ```
23
+ Alternatively, you can download the most up-to-date version from my github repository:
24
+ ```bash
25
+ pip install git+https://github.com/ProfesseurShadoko/oakley.git
26
+ ```
27
+
28
+ ## Quick examples
29
+
30
+ Colored strings
31
+
32
+ ```python
33
+ from oakley import cstr
34
+ print(cstr('hello world').green().bold())
35
+ print(f"Progress: {cstr('ok'):g}") # short color spec
36
+ print(f"{cstr('Done'):gb}") # in green and bold
37
+ ```
38
+
39
+ Pretty messages
40
+
41
+ ```python
42
+ from oakley import Message
43
+ Message("Build succeeded", "#") # green success prefix
44
+ Message("Something might be wrong", "?")
45
+ ```
46
+
47
+ Tasks and timing
48
+
49
+ ```python
50
+ from oakley import Task
51
+ import time
52
+
53
+ with Task("Compute something heavy"):
54
+ time.sleep(1.2)
55
+
56
+ ```
57
+
58
+ Progress bar
59
+
60
+ ```python
61
+ from oakley import ProgressBar
62
+ import time
63
+
64
+ for i in ProgressBar(range(50), size=50):
65
+ time.sleep(0.02)
66
+ if i == 25:
67
+ ProgressBar.whisper("Halfway there!")
68
+ ```
69
+
70
+ Status helpers
71
+
72
+ ```python
73
+ from oakley import MemoryView, TODO
74
+ MemoryView() # prints a short memory usage line (requires psutil)
75
+ TODO("Refactor the parser")
76
+ ```
77
+
78
+ Mute and indentation
79
+
80
+ ```python
81
+ from oakley import MutableClass, Message
82
+
83
+ MutableClass.mute() # globally mute printing
84
+ MutableClass.unmute()
85
+
86
+ with Message.mute():
87
+ Message.print("This won't be printed")
88
+ Message.print("This will be printed again!")
89
+
90
+ with Message("The following messages will be indented"): # increase indentation for nested prints
91
+ Message.print("This will be indented")
92
+ MemoryView() # also indented
93
+ Message("This won't be indented")
94
+ ```
95
+
96
+ ## Examples
97
+
98
+ Take a look at [this notebook](https://github.com/ProfesseurShadoko/oakley/blob/main/example.ipynb) for the most detailed and up to date examples.
99
+
100
+ Alternatively, run the command:
101
+ ```bash
102
+ python -m oakley.<filename_without_dot_py>
103
+ ```
104
+ to see examples for each object.
105
+
106
+
107
+ ## Development notes
108
+
109
+ - The package is intentionally tiny and uses ANSI escape sequences for coloring; compatibility is best on UNIX-like terminals.
110
+ - `MemoryView` depends on `psutil` — the package runs fine even when `psutil` is not available, but the `MemoryView` object cannot be used.
111
+ - There are simple demo blocks in each module under `if __name__ == '__main__'` for manual testing.
@@ -0,0 +1,6 @@
1
+
2
+ from .fancy_string import cstr
3
+ from .message import Message
4
+ from .progress_bar import ProgressBar
5
+ from .task import Task
6
+ from .status import MemoryView, TODO, DateTime
@@ -0,0 +1,34 @@
1
+
2
+ import json
3
+ import os
4
+
5
+ _default_config = {
6
+ "terminal_width": -1, # if -1, auto-detect,
7
+ "spinner": [],
8
+ }
9
+
10
+ # 1. Load the config.json file if it exists.
11
+ _config_path = os.path.join(os.path.dirname(__file__), 'config.json')
12
+
13
+ if not os.path.exists(_config_path):
14
+ # if not exist create it with default settings # should not happen!
15
+ with open(_config_path, 'w') as f:
16
+ json.dump(_default_config, f, indent=4)
17
+
18
+ with open(_config_path, 'r') as f:
19
+ file_config = json.load(f)
20
+ _default_config.update(file_config)
21
+
22
+
23
+ class ConfigDict(dict):
24
+
25
+ def __setitem__(self, key, value):
26
+ super().__setitem__(key, value)
27
+ # directly update the config file on every change
28
+ with open(_config_path, 'w') as f:
29
+ json.dump(self, f, indent=4)
30
+
31
+ print("[C] Config updated:", key, "=", value)
32
+
33
+
34
+ config = ConfigDict(_default_config) # put the dictionnary inside. default config contains the loaded file already.
@@ -0,0 +1,32 @@
1
+
2
+ import traceback as tb
3
+ from .fancy_string import cstr
4
+
5
+
6
+
7
+ class FancyCM:
8
+ """
9
+ Updates some counter on enter/exit.
10
+ """
11
+ lvl = 0
12
+
13
+ def __enter__(self):
14
+ FancyCM.lvl += 1
15
+
16
+ def __exit__(self, exc_type, exc_value, traceback):
17
+ FancyCM.lvl -= 1
18
+ if exc_type and FancyCM.lvl == 0:
19
+ print(f"Exception occurred: {cstr(exc_type.__name__):r} ({cstr(exc_value):y})")
20
+ tb.print_tb(traceback)
21
+
22
+
23
+
24
+ if __name__ == '__main__':
25
+
26
+ with FancyCM():
27
+ print("This was printed inside the context manager")
28
+ with FancyCM():
29
+ print("This was printed inside the nested context manager. Now an error will occure.")
30
+ x = 1/0
31
+ print("This will not be printed.")
32
+
@@ -0,0 +1,237 @@
1
+
2
+ from typing import Literal
3
+ import re
4
+ ANSI_RE = re.compile(r'\033\[[0-9;]*m')
5
+ from .print_stack import in_notebook
6
+
7
+ class Cstr(str):
8
+ """
9
+ Class inheritting for type string, with a few additional methods for coloring the string when printed to the console.
10
+
11
+ Methods:
12
+ green: Returns the string in green color
13
+ blue: Returns the string in blue color
14
+ red: Returns the string in red color
15
+ yellow: Returns the string in yellow color
16
+ bold: Returns the string in bold font
17
+ underline: Returns the string with underline
18
+ italic: Returns the string in italic font
19
+ strikethrough: Returns the string with strikethrough
20
+ highlight: Returns the string with highlighted background
21
+
22
+ Format:
23
+ print(f'{ColoredString("This is a colored string"):green}') # prints the string in green color
24
+ print(f'{ColoredString("This is a colored string"):g}') # prints the string in green color
25
+
26
+ """
27
+
28
+ _COLORS = {
29
+ 'green': '\033[92m',
30
+ 'blue': '\033[94m',
31
+ 'red': '\033[91m',
32
+ 'yellow': '\033[93m',
33
+ 'magenta': '\033[95m',
34
+ 'cyan': '\033[96m',
35
+ 'reset': '\033[0m',
36
+
37
+ 'bold': '\033[1m',
38
+ 'underline': '\033[4m',
39
+ 'italic': '\033[3m',
40
+ 'strikethrough': '\033[9m',
41
+ 'highlight': '\033[7m',
42
+ }
43
+
44
+ def __init__(self,string:str):
45
+ """
46
+ Args:
47
+ string (str): The string to be printed in color (can also be anything that can be converted to a string using str() function)
48
+ """
49
+ super().__init__() # how the hell does this work???
50
+
51
+
52
+ ##############
53
+ ### COLORS ###
54
+ ##############
55
+
56
+ def green(self) -> 'Cstr':
57
+ return self.__class__(
58
+ self._COLORS["green"] + self + self._COLORS["reset"]
59
+ )
60
+
61
+ def blue(self) -> 'Cstr':
62
+ return self.__class__(
63
+ self._COLORS["blue"] + self + self._COLORS["reset"]
64
+ )
65
+
66
+ def red(self) -> 'Cstr':
67
+ return self.__class__(
68
+ self._COLORS["red"] + self + self._COLORS["reset"]
69
+ )
70
+
71
+ def yellow(self) -> 'Cstr':
72
+ return self.__class__(
73
+ self._COLORS["yellow"] + self + self._COLORS["reset"]
74
+ )
75
+
76
+ def magenta(self) -> 'Cstr':
77
+ return self.__class__(
78
+ self._COLORS["magenta"] + self + self._COLORS["reset"]
79
+ )
80
+
81
+ def cyan(self) -> 'Cstr':
82
+ return self.__class__(
83
+ self._COLORS["cyan"] + self + self._COLORS["reset"]
84
+ )
85
+
86
+ def white(self) -> 'Cstr':
87
+ return self
88
+
89
+
90
+ #############
91
+ ### FONTS ###
92
+ #############
93
+
94
+ def bold(self) -> 'Cstr':
95
+ return self.__class__(
96
+ self._COLORS["bold"] + self + self._COLORS["reset"]
97
+ )
98
+
99
+ def underline(self) -> 'Cstr':
100
+ return self.__class__(
101
+ self._COLORS["underline"] + self + self._COLORS["reset"]
102
+ )
103
+
104
+ def italic(self) -> 'Cstr':
105
+ return self.__class__(
106
+ self._COLORS["italic"] + self + self._COLORS["reset"]
107
+ )
108
+
109
+ def strikethrough(self) -> 'Cstr':
110
+ return self.__class__(
111
+ self._COLORS["strikethrough"] + self + self._COLORS["reset"]
112
+ )
113
+
114
+ def highlight(self) -> 'Cstr':
115
+ return self.__class__(
116
+ self._COLORS["highlight"] + self + self._COLORS["reset"]
117
+ )
118
+
119
+
120
+ ##############
121
+ ### FORMAT ###
122
+ ##############
123
+
124
+ def __format__(self, format_spec:str) -> 'Cstr':
125
+ if not format_spec:
126
+ return self
127
+
128
+ colors = [
129
+ 'green', 'blue', 'red', 'yellow', 'magenta', 'cyan', 'white'
130
+ ]
131
+ fonts = [
132
+ 'bold', 'underline', 'italic', 'strikethrough', 'highlight'
133
+ ]
134
+
135
+ color_spec = format_spec[0]
136
+ if len(format_spec) > 1:
137
+ font_spec = format_spec[1:]
138
+ else:
139
+ font_spec = ''
140
+ assert len(format_spec) <= 2, f"Invalid format specifier: {format_spec}. Must be one or two characters long."
141
+
142
+ allowed_color_specs = [c[0] for c in colors]
143
+ allowed_font_specs = [f[0] for f in fonts] + ['']
144
+
145
+ assert color_spec in allowed_color_specs, f"Invalid format specifier: {format_spec}. Must be one of {allowed_color_specs}."
146
+ assert font_spec in allowed_font_specs, f"Invalid format specifier: {format_spec}. Must be one of {allowed_font_specs}."
147
+
148
+ out = self
149
+
150
+ # 1. Add the color to the string
151
+ color = [c for c in colors if c.startswith(color_spec)][0] # there is only one anyway
152
+ out = getattr(out, color)()
153
+
154
+ # 2. Add the font to the string
155
+ if font_spec:
156
+ font = [f for f in fonts if f.startswith(font_spec)][0]
157
+ out = getattr(out, font)()
158
+
159
+ return out
160
+
161
+ def length(self) -> int:
162
+ """
163
+ Returns the length of the string without ANSI escape codes.
164
+ """
165
+ if not in_notebook:
166
+ return len(ANSI_RE.sub('', self))
167
+ else:
168
+ return len(self)
169
+
170
+
171
+ def cstr(obj:object, format_spec:str='') -> 'Cstr':
172
+ """
173
+ Convert an object into a color-capable string (`Cstr`).
174
+
175
+ This function formats `obj` using Python's built-in ``format`` machinery
176
+ (e.g. for floats, integers, or custom ``__format__`` implementations),
177
+ and then wraps the resulting text into a :class:`Cstr` object.
178
+ The returned `Cstr` instance supports ANSI colorization, text styles
179
+ (bold, underline, italic, …), and compact format specifiers.
180
+
181
+ Parameters
182
+ ----------
183
+ obj : object
184
+ The object to convert to a colored string. Any object that can be
185
+ formatted via ``format(obj, format_spec)`` is accepted.
186
+ format_spec : str, optional
187
+ Standard Python format specification applied *before*
188
+ converting the output to a `Cstr`.
189
+ For example: ``'.2f'``, ``'05d'``, ``'>10s'``, etc.
190
+
191
+ Returns
192
+ -------
193
+ Cstr
194
+ A colored-string wrapper that supports methods such as
195
+ ``.green()``, ``.red()``, ``.bold()``, ``.underline()``,
196
+ as well as compact format usage inside f-strings (e.g. ``:gb``).
197
+
198
+ Notes
199
+ -----
200
+ - Color and style transformations are applied *after* formatting.
201
+ - Inside f-strings, short format specifiers allow concise styling:
202
+ ``g`` → green, ``r`` → red, ``b`` → blue,
203
+ combined with ``b`` for bold, ``u`` for underline, …
204
+ Examples: ``:gb`` (green + bold), ``:ru`` (red + underline).
205
+
206
+ Examples
207
+ --------
208
+ Basic usage:
209
+
210
+ >>> print(cstr("Hello").green())
211
+ Hello # in green
212
+
213
+ With numeric formatting:
214
+
215
+ >>> x = 3.14159
216
+ >>> print(cstr(x, '.2f').cyan())
217
+ 3.14 # in cyan
218
+
219
+ Using short form styling inside an f-string:
220
+
221
+ >>> print(f"Value: {cstr('OK'):gb}")
222
+ Value: OK # green + bold
223
+ """
224
+ return Cstr(format(obj, format_spec))
225
+
226
+
227
+
228
+ if __name__ == '__main__':
229
+ x = 3.1416
230
+ print(cstr(x, '.2f').green().bold())
231
+ print(f"This was the number PI in {cstr('green'):g} color.")
232
+
233
+ # testing the length method
234
+ s = "Hello, World!"
235
+ colored_s = cstr(s).red().bold().underline()
236
+ print(f"Original length: {len(s)}, Colored length: {colored_s.length()}, len(colored_s): {len(colored_s)}")
237
+