gsplot 0.0.1__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.
- gsplot/__init__.py +98 -0
- gsplot/base/base.py +518 -0
- gsplot/base/base_alias_validator.py +155 -0
- gsplot/color/colormap.py +218 -0
- gsplot/config/config.py +422 -0
- gsplot/data/load_file.py +188 -0
- gsplot/figure/axes.py +361 -0
- gsplot/figure/axes_base.py +952 -0
- gsplot/figure/figure_tools.py +66 -0
- gsplot/figure/show.py +205 -0
- gsplot/figure/store.py +119 -0
- gsplot/hello_world/hello_world.py +23 -0
- gsplot/logger.py +155 -0
- gsplot/path/path.py +227 -0
- gsplot/plot/line.py +328 -0
- gsplot/plot/line_base.py +272 -0
- gsplot/plot/line_colormap_base.py +120 -0
- gsplot/plot/line_colormap_dashed.py +540 -0
- gsplot/plot/line_colormap_solid.py +289 -0
- gsplot/plot/scatter.py +228 -0
- gsplot/plot/scatter_colormap.py +296 -0
- gsplot/style/graph.py +466 -0
- gsplot/style/label.py +866 -0
- gsplot/style/legend.py +469 -0
- gsplot/style/legend_colormap.py +381 -0
- gsplot/style/ticks.py +167 -0
- gsplot/version.py +2 -0
- gsplot-0.0.1.dist-info/LICENSE +21 -0
- gsplot-0.0.1.dist-info/METADATA +82 -0
- gsplot-0.0.1.dist-info/RECORD +31 -0
- gsplot-0.0.1.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from matplotlib import pyplot as plt
|
|
4
|
+
from numpy.typing import NDArray
|
|
5
|
+
|
|
6
|
+
__all__: list[str] = ["get_figure_size"]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FigureLayout:
|
|
10
|
+
"""
|
|
11
|
+
A utility class for retrieving the size of the current Matplotlib figure.
|
|
12
|
+
|
|
13
|
+
This class provides a method to get the size of the current figure in inches.
|
|
14
|
+
|
|
15
|
+
Methods
|
|
16
|
+
--------------------
|
|
17
|
+
get_figure_size()
|
|
18
|
+
Retrieves the size of the current figure in inches.
|
|
19
|
+
|
|
20
|
+
Examples
|
|
21
|
+
--------------------
|
|
22
|
+
>>> layout = FigureLayout()
|
|
23
|
+
>>> size = layout.get_figure_size()
|
|
24
|
+
>>> print(size)
|
|
25
|
+
array([10., 6.]) # Example output (width, height in inches)
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def get_figure_size(self) -> NDArray[Any]:
|
|
29
|
+
"""
|
|
30
|
+
Retrieves the size of the current Matplotlib figure in inches.
|
|
31
|
+
|
|
32
|
+
Returns
|
|
33
|
+
--------------------
|
|
34
|
+
numpy.ndarray
|
|
35
|
+
The width and height of the current figure in inches as a NumPy array.
|
|
36
|
+
|
|
37
|
+
Examples
|
|
38
|
+
--------------------
|
|
39
|
+
>>> layout = FigureLayout()
|
|
40
|
+
>>> size = layout.get_figure_size()
|
|
41
|
+
>>> print(size)
|
|
42
|
+
array([10., 6.]) # Example output (width, height in inches)
|
|
43
|
+
"""
|
|
44
|
+
figure_size = plt.gcf().get_size_inches()
|
|
45
|
+
return figure_size
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def get_figure_size() -> NDArray[Any]:
|
|
49
|
+
"""
|
|
50
|
+
A convenient function to retrieve the size of the current Matplotlib figure.
|
|
51
|
+
|
|
52
|
+
This function is a shorthand for calling `FigureLayout().get_figure_size()`.
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
--------------------
|
|
56
|
+
numpy.ndarray
|
|
57
|
+
The width and height of the current figure in inches as a NumPy array.
|
|
58
|
+
|
|
59
|
+
Examples
|
|
60
|
+
--------------------
|
|
61
|
+
>>> import gsplot as gs
|
|
62
|
+
>>> size = gs.get_figure_size()
|
|
63
|
+
>>> print(size)
|
|
64
|
+
array([10., 6.]) # Example output (width, height in inches)
|
|
65
|
+
"""
|
|
66
|
+
return FigureLayout().get_figure_size()
|
gsplot/figure/show.py
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
|
|
5
|
+
from ..base.base import CreateClassParams, ParamsGetter, bind_passed_params
|
|
6
|
+
from .store import StoreSingleton
|
|
7
|
+
|
|
8
|
+
__all__: list[str] = ["show"]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Show:
|
|
12
|
+
"""
|
|
13
|
+
A utility class for managing figure saving and displaying in Matplotlib.
|
|
14
|
+
|
|
15
|
+
This class provides functionality to save the current figure in multiple formats
|
|
16
|
+
and optionally display it.
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
--------------------
|
|
20
|
+
name : str, optional
|
|
21
|
+
The base name for saved figure files (default is "gsplot").
|
|
22
|
+
ft_list : list of str, optional
|
|
23
|
+
A list of file formats for saving the figure (default is ["png", "pdf"]).
|
|
24
|
+
dpi : float, optional
|
|
25
|
+
The resolution (dots per inch) for saving the figure (default is 600).
|
|
26
|
+
show : bool, optional
|
|
27
|
+
Whether to display the figure (default is True).
|
|
28
|
+
*args : Any
|
|
29
|
+
Additional positional arguments passed to `plt.savefig`.
|
|
30
|
+
**kwargs : Any
|
|
31
|
+
Additional keyword arguments passed to `plt.savefig`.
|
|
32
|
+
|
|
33
|
+
Attributes
|
|
34
|
+
--------------------
|
|
35
|
+
name : str
|
|
36
|
+
The base name for saved figure files.
|
|
37
|
+
ft_list : list of str
|
|
38
|
+
A list of file formats for saving the figure.
|
|
39
|
+
dpi : float
|
|
40
|
+
The resolution for saving the figure.
|
|
41
|
+
show : bool
|
|
42
|
+
Whether to display the figure.
|
|
43
|
+
args : Any
|
|
44
|
+
Additional positional arguments passed to `plt.savefig`.
|
|
45
|
+
kwargs : Any
|
|
46
|
+
Additional keyword arguments passed to `plt.savefig`.
|
|
47
|
+
_store_singleton : StoreSingleton
|
|
48
|
+
A singleton instance for managing the storage state.
|
|
49
|
+
|
|
50
|
+
Methods
|
|
51
|
+
--------------------
|
|
52
|
+
store_fig()
|
|
53
|
+
Saves the current figure in the specified formats.
|
|
54
|
+
get_store()
|
|
55
|
+
Retrieves the storage state from the singleton instance.
|
|
56
|
+
show_fig()
|
|
57
|
+
Displays the current figure if `show` is True.
|
|
58
|
+
|
|
59
|
+
Examples
|
|
60
|
+
--------------------
|
|
61
|
+
>>> show_instance = Show(name="example", ft_list=["png", "jpg"], dpi=300, show=False)
|
|
62
|
+
>>> show_instance.store_fig()
|
|
63
|
+
>>> show_instance.show_fig() # Will not display the figure since `show=False`
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def __init__(
|
|
67
|
+
self,
|
|
68
|
+
name: str = "gsplot",
|
|
69
|
+
ft_list: list[str] = ["png", "pdf"],
|
|
70
|
+
dpi: float = 600,
|
|
71
|
+
show: bool = True,
|
|
72
|
+
*args: Any,
|
|
73
|
+
**kwargs: Any,
|
|
74
|
+
):
|
|
75
|
+
|
|
76
|
+
self.name: str = name
|
|
77
|
+
self.ft_list: list[str] = ft_list
|
|
78
|
+
self.dpi: float = dpi
|
|
79
|
+
self.show: bool = show
|
|
80
|
+
self.args: Any = args
|
|
81
|
+
self.kwargs: Any = kwargs
|
|
82
|
+
|
|
83
|
+
self._store_singleton: StoreSingleton = StoreSingleton()
|
|
84
|
+
|
|
85
|
+
def store_fig(self) -> None:
|
|
86
|
+
"""
|
|
87
|
+
Saves the current figure in the specified formats.
|
|
88
|
+
|
|
89
|
+
This method uses the provided file formats and resolution to save the figure.
|
|
90
|
+
|
|
91
|
+
Raises
|
|
92
|
+
--------------------
|
|
93
|
+
Exception
|
|
94
|
+
If an error occurs during saving, a warning is printed.
|
|
95
|
+
|
|
96
|
+
Examples
|
|
97
|
+
--------------------
|
|
98
|
+
>>> show_instance = Show(name="example", ft_list=["png", "jpg"], dpi=300)
|
|
99
|
+
>>> show_instance.store_fig()
|
|
100
|
+
"""
|
|
101
|
+
if self.get_store():
|
|
102
|
+
# save figure
|
|
103
|
+
fname_list: list[str] = [f"{self.name}.{ft}" for ft in self.ft_list]
|
|
104
|
+
|
|
105
|
+
# !TODO: figure out **kwargs for savefig. None, or *args, **kwargs
|
|
106
|
+
for fname in fname_list:
|
|
107
|
+
try:
|
|
108
|
+
plt.savefig(
|
|
109
|
+
fname,
|
|
110
|
+
bbox_inches="tight",
|
|
111
|
+
dpi=self.dpi,
|
|
112
|
+
*self.args,
|
|
113
|
+
**self.kwargs,
|
|
114
|
+
)
|
|
115
|
+
except Exception as e:
|
|
116
|
+
print(f"Error saving figure: {e}")
|
|
117
|
+
plt.savefig(fname, bbox_inches="tight", dpi=self.dpi)
|
|
118
|
+
|
|
119
|
+
def get_store(self) -> bool | int:
|
|
120
|
+
"""
|
|
121
|
+
Retrieves the storage state from the singleton instance.
|
|
122
|
+
|
|
123
|
+
Returns
|
|
124
|
+
--------------------
|
|
125
|
+
bool or int
|
|
126
|
+
The storage state indicating whether saving is enabled.
|
|
127
|
+
|
|
128
|
+
Examples
|
|
129
|
+
--------------------
|
|
130
|
+
>>> show_instance = Show()
|
|
131
|
+
>>> print(show_instance.get_store())
|
|
132
|
+
True
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
store: bool | int = self._store_singleton.store
|
|
136
|
+
return store
|
|
137
|
+
|
|
138
|
+
def show_fig(self) -> None:
|
|
139
|
+
"""
|
|
140
|
+
Displays the current figure if `show` is True.
|
|
141
|
+
|
|
142
|
+
Examples
|
|
143
|
+
--------------------
|
|
144
|
+
>>> show_instance = Show(show=True)
|
|
145
|
+
>>> show_instance.show_fig()
|
|
146
|
+
"""
|
|
147
|
+
if self.show:
|
|
148
|
+
plt.show()
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@bind_passed_params()
|
|
152
|
+
def show(
|
|
153
|
+
fname: str = "gsplot",
|
|
154
|
+
ft_list: list[str] = ["png", "pdf"],
|
|
155
|
+
dpi: float = 600,
|
|
156
|
+
show: bool = True,
|
|
157
|
+
*args: Any,
|
|
158
|
+
**kwargs: Any,
|
|
159
|
+
) -> None:
|
|
160
|
+
"""
|
|
161
|
+
A convenience function to save and optionally display a Matplotlib figure.
|
|
162
|
+
|
|
163
|
+
This function wraps the `Show` class for easier access and management of figure
|
|
164
|
+
saving and displaying.
|
|
165
|
+
|
|
166
|
+
Parameters
|
|
167
|
+
--------------------
|
|
168
|
+
fname : str, optional
|
|
169
|
+
The base name for saved figure files (default is "gsplot").
|
|
170
|
+
ft_list : list of str, optional
|
|
171
|
+
A list of file formats for saving the figure (default is ["png", "pdf"]).
|
|
172
|
+
dpi : float, optional
|
|
173
|
+
The resolution (dots per inch) for saving the figure (default is 600).
|
|
174
|
+
show : bool, optional
|
|
175
|
+
Whether to display the figure (default is True).
|
|
176
|
+
*args : Any
|
|
177
|
+
Additional positional arguments passed to `plt.savefig`.
|
|
178
|
+
**kwargs : Any
|
|
179
|
+
Additional keyword arguments passed to `plt.savefig`.
|
|
180
|
+
|
|
181
|
+
Notes
|
|
182
|
+
--------------------
|
|
183
|
+
This function utilizes the `ParamsGetter` to retrieve bound parameters and
|
|
184
|
+
the `CreateClassParams` class to handle the merging of default, configuration,
|
|
185
|
+
and passed parameters.
|
|
186
|
+
|
|
187
|
+
Examples
|
|
188
|
+
--------------------
|
|
189
|
+
>>> import gsplot as gs
|
|
190
|
+
>>> gs.show(fname="example", ft_list=["png", "jpg"], dpi=300, show=True)
|
|
191
|
+
"""
|
|
192
|
+
passed_params: dict[str, Any] = ParamsGetter("passed_params").get_bound_params()
|
|
193
|
+
class_params = CreateClassParams(passed_params).get_class_params()
|
|
194
|
+
|
|
195
|
+
_show: Show = Show(
|
|
196
|
+
class_params["fname"],
|
|
197
|
+
class_params["ft_list"],
|
|
198
|
+
class_params["dpi"],
|
|
199
|
+
class_params["show"],
|
|
200
|
+
*class_params["args"],
|
|
201
|
+
**class_params["kwargs"],
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
_show.store_fig()
|
|
205
|
+
_show.show_fig()
|
gsplot/figure/store.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import threading
|
|
4
|
+
|
|
5
|
+
__all__: list[str] = []
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class StoreSingleton:
|
|
9
|
+
"""
|
|
10
|
+
A thread-safe singleton class for managing a shared storage state.
|
|
11
|
+
|
|
12
|
+
This class ensures that a single instance is used to manage the storage state
|
|
13
|
+
across an application. The storage state can be a boolean or an integer (0 or 1),
|
|
14
|
+
providing flexibility for different use cases.
|
|
15
|
+
|
|
16
|
+
Attributes
|
|
17
|
+
--------------------
|
|
18
|
+
store : bool or int
|
|
19
|
+
The current storage state, which can be either a boolean or an integer (0 or 1).
|
|
20
|
+
|
|
21
|
+
Methods
|
|
22
|
+
--------------------
|
|
23
|
+
store
|
|
24
|
+
Retrieves the current storage state.
|
|
25
|
+
store(value)
|
|
26
|
+
Sets the storage state to a boolean or an integer (0 or 1).
|
|
27
|
+
|
|
28
|
+
Examples
|
|
29
|
+
--------------------
|
|
30
|
+
>>> singleton = StoreSingleton()
|
|
31
|
+
>>> print(singleton.store)
|
|
32
|
+
False # Default value
|
|
33
|
+
|
|
34
|
+
>>> singleton.store = True
|
|
35
|
+
>>> print(singleton.store)
|
|
36
|
+
True
|
|
37
|
+
|
|
38
|
+
>>> singleton.store = 1
|
|
39
|
+
>>> print(singleton.store)
|
|
40
|
+
1
|
|
41
|
+
|
|
42
|
+
>>> singleton.store = "invalid" # Raises ValueError
|
|
43
|
+
Traceback (most recent call last):
|
|
44
|
+
...
|
|
45
|
+
ValueError: Store must be a boolean or integer.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
_instance: StoreSingleton | None = None
|
|
49
|
+
_lock: threading.Lock = threading.Lock() # Lock to ensure thread safety
|
|
50
|
+
|
|
51
|
+
def __new__(cls) -> "StoreSingleton":
|
|
52
|
+
with cls._lock:
|
|
53
|
+
if cls._instance is None:
|
|
54
|
+
cls._instance = super(StoreSingleton, cls).__new__(cls)
|
|
55
|
+
cls._instance._initialize_store()
|
|
56
|
+
return cls._instance
|
|
57
|
+
|
|
58
|
+
def _initialize_store(self) -> None:
|
|
59
|
+
"""
|
|
60
|
+
Initializes the storage state to its default value (False).
|
|
61
|
+
"""
|
|
62
|
+
# Explicitly initialize the instance variable with a type hint
|
|
63
|
+
self._store: bool | int = False
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def store(self) -> bool | int:
|
|
67
|
+
"""
|
|
68
|
+
Retrieves the current storage state.
|
|
69
|
+
|
|
70
|
+
Returns
|
|
71
|
+
--------------------
|
|
72
|
+
bool or int
|
|
73
|
+
The current storage state.
|
|
74
|
+
|
|
75
|
+
Examples
|
|
76
|
+
--------------------
|
|
77
|
+
>>> singleton = StoreSingleton()
|
|
78
|
+
>>> print(singleton.store)
|
|
79
|
+
False
|
|
80
|
+
"""
|
|
81
|
+
return self._store
|
|
82
|
+
|
|
83
|
+
@store.setter
|
|
84
|
+
def store(self, value: bool | int) -> None:
|
|
85
|
+
"""
|
|
86
|
+
Sets the storage state.
|
|
87
|
+
|
|
88
|
+
Parameters
|
|
89
|
+
--------------------
|
|
90
|
+
value : bool or int
|
|
91
|
+
The new storage state. Must be a boolean or an integer (0 or 1).
|
|
92
|
+
|
|
93
|
+
Raises
|
|
94
|
+
--------------------
|
|
95
|
+
ValueError
|
|
96
|
+
If the value is not a boolean or integer, or if an integer is not 0 or 1.
|
|
97
|
+
|
|
98
|
+
Examples
|
|
99
|
+
--------------------
|
|
100
|
+
>>> singleton = StoreSingleton()
|
|
101
|
+
>>> singleton.store = True
|
|
102
|
+
>>> print(singleton.store)
|
|
103
|
+
True
|
|
104
|
+
|
|
105
|
+
>>> singleton.store = 1
|
|
106
|
+
>>> print(singleton.store)
|
|
107
|
+
1
|
|
108
|
+
|
|
109
|
+
>>> singleton.store = "invalid" # Raises ValueError
|
|
110
|
+
Traceback (most recent call last):
|
|
111
|
+
...
|
|
112
|
+
ValueError: Store must be a boolean or integer.
|
|
113
|
+
"""
|
|
114
|
+
if not isinstance(value, (bool, int)):
|
|
115
|
+
raise ValueError("Store must be a boolean or integer.")
|
|
116
|
+
if isinstance(value, int) and value not in [0, 1]:
|
|
117
|
+
raise ValueError("Store must be 0 or 1 if integer.")
|
|
118
|
+
|
|
119
|
+
self._store = value
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from rich import print
|
|
2
|
+
|
|
3
|
+
from ..version import __commit__, __version__
|
|
4
|
+
|
|
5
|
+
__all__ = ["hello_world"]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def hello_world() -> None:
|
|
9
|
+
"""
|
|
10
|
+
Print the version, commit hash, and an ASCII art of the logo.
|
|
11
|
+
"""
|
|
12
|
+
ascii_art = r"""
|
|
13
|
+
██████╗ ███████╗██████╗ ██╗ ██████╗ ████████╗
|
|
14
|
+
██╔════╝ ██╔════╝██╔══██╗██║ ██╔═══██╗╚══██╔══╝
|
|
15
|
+
██║ ███╗███████╗██████╔╝██║ ██║ ██║ ██║
|
|
16
|
+
██║ ██║╚════██║██╔═══╝ ██║ ██║ ██║ ██║
|
|
17
|
+
╚██████╔╝███████║██║ ███████╗╚██████╔╝ ██║
|
|
18
|
+
╚═════╝ ╚══════╝╚═╝ ╚══════╝ ╚═════╝ ╚═╝
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
print(f"Version: {__version__}")
|
|
22
|
+
print(f"Commit : {__commit__}")
|
|
23
|
+
print(ascii_art)
|
gsplot/logger.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from typing import Any, cast
|
|
4
|
+
|
|
5
|
+
import yaml
|
|
6
|
+
from rich import print
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
from rich.panel import Panel
|
|
9
|
+
from rich.text import Text
|
|
10
|
+
|
|
11
|
+
from .version import __commit__, __version__
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Logger:
|
|
15
|
+
HOME = os.path.expanduser("~")
|
|
16
|
+
LOG_PATH = os.path.join(HOME, ".config", "gsplot")
|
|
17
|
+
LOG_FILE_NAME = "gsplot_log.yml"
|
|
18
|
+
LOG_FILE_PATH = os.path.join(LOG_PATH, LOG_FILE_NAME)
|
|
19
|
+
|
|
20
|
+
def __init__(self):
|
|
21
|
+
self.console = Console()
|
|
22
|
+
self.log: dict[str, Any] = {}
|
|
23
|
+
self.version_idx: int | None = None
|
|
24
|
+
self.commit_idx: int | None = None
|
|
25
|
+
|
|
26
|
+
self.is_error: bool = False
|
|
27
|
+
|
|
28
|
+
self.create_file()
|
|
29
|
+
self.log = self.read_file()
|
|
30
|
+
|
|
31
|
+
def _create_empty_file(self):
|
|
32
|
+
with open(self.LOG_FILE_PATH, "w") as file:
|
|
33
|
+
file.write("{}")
|
|
34
|
+
|
|
35
|
+
def create_file(self):
|
|
36
|
+
if not os.path.exists(self.LOG_PATH):
|
|
37
|
+
os.makedirs(self.LOG_PATH)
|
|
38
|
+
|
|
39
|
+
# if YAML file does not exist, create it
|
|
40
|
+
if not os.path.exists(self.LOG_FILE_PATH):
|
|
41
|
+
self._create_empty_file()
|
|
42
|
+
|
|
43
|
+
def _init_log(self):
|
|
44
|
+
return {"versions": []}
|
|
45
|
+
|
|
46
|
+
def read_file(self) -> dict[str, Any]:
|
|
47
|
+
with open(self.LOG_FILE_PATH, "r") as file:
|
|
48
|
+
log = yaml.safe_load(file)
|
|
49
|
+
|
|
50
|
+
if not log or not log.get("versions"):
|
|
51
|
+
log = self._init_log()
|
|
52
|
+
|
|
53
|
+
return cast(dict[str, Any], log)
|
|
54
|
+
|
|
55
|
+
def get_date(self):
|
|
56
|
+
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
57
|
+
|
|
58
|
+
def _error_message(self, e: Exception) -> None:
|
|
59
|
+
warning_message = f"[bold yellow]gsplot log file is corrupted. [bold green]See gsplot_log.yml file: {self.LOG_FILE_PATH}\n[bold red]Error: {e}"
|
|
60
|
+
|
|
61
|
+
self.console.print(
|
|
62
|
+
Panel(
|
|
63
|
+
Text.from_markup(warning_message),
|
|
64
|
+
title="[bold yellow]Warning",
|
|
65
|
+
style="bold yellow",
|
|
66
|
+
)
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def _get_versions_from_log(self) -> list[dict[str, str]]:
|
|
70
|
+
try:
|
|
71
|
+
return cast(list[dict[str, str]], self.log.get("versions", []))
|
|
72
|
+
except Exception as e:
|
|
73
|
+
self.is_error = True
|
|
74
|
+
self._error_message(e)
|
|
75
|
+
return []
|
|
76
|
+
|
|
77
|
+
def _get_commits_from_version(self, version: str) -> list[dict[str, str]]:
|
|
78
|
+
try:
|
|
79
|
+
return next(
|
|
80
|
+
(
|
|
81
|
+
v.get("commits", [])
|
|
82
|
+
for v in self.log["versions"]
|
|
83
|
+
if v.get("version") == version
|
|
84
|
+
),
|
|
85
|
+
[],
|
|
86
|
+
)
|
|
87
|
+
except Exception as e:
|
|
88
|
+
self.is_error = True
|
|
89
|
+
self._error_message(e)
|
|
90
|
+
return []
|
|
91
|
+
|
|
92
|
+
def _has_same_version(self, version: str) -> bool:
|
|
93
|
+
# Retrieve the list of versions from the log
|
|
94
|
+
versions: list[dict[str, str]] | None = self._get_versions_from_log()
|
|
95
|
+
|
|
96
|
+
if not versions:
|
|
97
|
+
return False
|
|
98
|
+
|
|
99
|
+
# Find the index of the version that matches the input
|
|
100
|
+
self.version_idx = next(
|
|
101
|
+
(i for i, v in enumerate(versions) if v.get("version") == version), None
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# Return True if a match is found, otherwise False
|
|
105
|
+
return self.version_idx is not None
|
|
106
|
+
|
|
107
|
+
def _has_same_commit(self, commit: str) -> bool:
|
|
108
|
+
# Get commits from the version
|
|
109
|
+
commits: list[dict[str, str]] = self._get_commits_from_version(__version__)
|
|
110
|
+
|
|
111
|
+
if not commits:
|
|
112
|
+
return False
|
|
113
|
+
|
|
114
|
+
# Find the commit in the list of commits
|
|
115
|
+
self.commit_idx = next(
|
|
116
|
+
(i for i, c in enumerate(commits) if c.get("commit") == commit), None
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# Return True if a match is found
|
|
120
|
+
return self.commit_idx is not None
|
|
121
|
+
|
|
122
|
+
def create_log(self):
|
|
123
|
+
if not self._has_same_version(__version__):
|
|
124
|
+
current = {
|
|
125
|
+
"version": __version__,
|
|
126
|
+
"commits": [{"commit": __commit__, "date": self.get_date()}],
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
self.log["versions"].append(current)
|
|
130
|
+
else:
|
|
131
|
+
if not self._has_same_commit(__commit__):
|
|
132
|
+
self.log["versions"][self.version_idx]["commits"].append(
|
|
133
|
+
{"commit": __commit__, "date": self.get_date()}
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
def write_log(self, log: dict[str, Any]) -> None:
|
|
137
|
+
with open(self.LOG_FILE_PATH, "w") as file:
|
|
138
|
+
yaml.dump(log, file, default_flow_style=False, sort_keys=False, indent=2)
|
|
139
|
+
|
|
140
|
+
def make_log(self) -> None:
|
|
141
|
+
if self.is_error:
|
|
142
|
+
return None
|
|
143
|
+
|
|
144
|
+
try:
|
|
145
|
+
self.create_log()
|
|
146
|
+
except Exception as e:
|
|
147
|
+
self.is_error = True
|
|
148
|
+
self._error_message(e)
|
|
149
|
+
|
|
150
|
+
self.write_log(self.log)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def logger():
|
|
154
|
+
_logger = Logger()
|
|
155
|
+
_logger.make_log()
|