corelp 1.0.36__py3-none-any.whl → 1.0.38__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.
- corelp/modules/Path_LP/test_Path.py +1 -1
- corelp/modules/rfrom_LP/test_rfrom.py +1 -1
- corelp/modules.json +0 -24
- {corelp-1.0.36.dist-info → corelp-1.0.38.dist-info}/METADATA +1 -6
- {corelp-1.0.36.dist-info → corelp-1.0.38.dist-info}/RECORD +6 -18
- {corelp-1.0.36.dist-info → corelp-1.0.38.dist-info}/WHEEL +1 -1
- corelp/modules/Section_LP/Section.py +0 -176
- corelp/modules/Section_LP/__init__.py +0 -0
- corelp/modules/Section_LP/test_Section.py +0 -43
- corelp/modules/main_LP/__init__.py +0 -0
- corelp/modules/main_LP/main.py +0 -251
- corelp/modules/main_LP/test_main.py +0 -74
- corelp/modules/print_LP/__init__.py +0 -0
- corelp/modules/print_LP/print.py +0 -326
- corelp/modules/print_LP/test_print.py +0 -108
- corelp/modules/user_inputs_LP/__init__.py +0 -0
- corelp/modules/user_inputs_LP/test_user_inputs.py +0 -46
- corelp/modules/user_inputs_LP/user_inputs.py +0 -87
corelp/modules.json
CHANGED
|
@@ -5,12 +5,6 @@
|
|
|
5
5
|
"module": "modules/Path_LP/Path",
|
|
6
6
|
"object": "Path"
|
|
7
7
|
},
|
|
8
|
-
"Section": {
|
|
9
|
-
"date": "2025-08-28",
|
|
10
|
-
"description": "This class defines decorator instances allowing to create section functions.",
|
|
11
|
-
"module": "modules/Section_LP/Section",
|
|
12
|
-
"object": "Section"
|
|
13
|
-
},
|
|
14
8
|
"debug": {
|
|
15
9
|
"date": "2025-08-25",
|
|
16
10
|
"description": "This function will give and create the debug folder for a given python file.",
|
|
@@ -35,18 +29,6 @@
|
|
|
35
29
|
"module": "modules/kwargsself_LP/kwargsself",
|
|
36
30
|
"object": "kwargsself"
|
|
37
31
|
},
|
|
38
|
-
"main": {
|
|
39
|
-
"date": "2025-08-28",
|
|
40
|
-
"description": "This function can decorate the main function of a script.",
|
|
41
|
-
"module": "modules/main_LP/main",
|
|
42
|
-
"object": "main"
|
|
43
|
-
},
|
|
44
|
-
"print": {
|
|
45
|
-
"date": "2025-08-27",
|
|
46
|
-
"description": "This function overrides python built in print function to add functionnalities.",
|
|
47
|
-
"module": "modules/print_LP/print",
|
|
48
|
-
"object": "print"
|
|
49
|
-
},
|
|
50
32
|
"prop": {
|
|
51
33
|
"date": "2025-08-25",
|
|
52
34
|
"description": "This function serves as an improved property decorator.",
|
|
@@ -70,11 +52,5 @@
|
|
|
70
52
|
"description": "This function will launch the testfile for the current file using pytest library.",
|
|
71
53
|
"module": "modules/test_LP/test",
|
|
72
54
|
"object": "test"
|
|
73
|
-
},
|
|
74
|
-
"user_inputs": {
|
|
75
|
-
"date": "2025-11-30",
|
|
76
|
-
"description": "Gets last user inputs dictionnary from global variables.",
|
|
77
|
-
"module": "modules/user_inputs_LP/user_inputs",
|
|
78
|
-
"object": "user_inputs"
|
|
79
55
|
}
|
|
80
56
|
}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: corelp
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.38
|
|
4
4
|
Summary: A library that gathers core functions for python programming.
|
|
5
|
-
Requires-Dist: joblib ; extra == 'script'
|
|
6
|
-
Requires-Dist: rich ; extra == 'script'
|
|
7
|
-
Requires-Dist: marimo ; extra == 'script'
|
|
8
5
|
Requires-Python: >=3.12
|
|
9
|
-
Provides-Extra: lib
|
|
10
|
-
Provides-Extra: script
|
|
11
6
|
Description-Content-Type: text/markdown
|
|
12
7
|
|
|
13
8
|
# coreLP
|
|
@@ -2,10 +2,7 @@ corelp/__init__.py,sha256=JMGz_b8Xz6heIsLVRtZpfpZ1DMF_Vsi-Xw8l7pnqy6c,684
|
|
|
2
2
|
corelp/icon_pythonLP.png,sha256=pg386kYEKGspDDRbRF0alOmHXPEm0geMoYIPaxEfQ_o,3805
|
|
3
3
|
corelp/modules/Path_LP/Path.py,sha256=wfvO1DuewIUSEA9_g66O5nCEp95Pr5XM-yxaOOEimTs,2418
|
|
4
4
|
corelp/modules/Path_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
corelp/modules/Path_LP/test_Path.py,sha256=
|
|
6
|
-
corelp/modules/Section_LP/Section.py,sha256=0uqvqzuBd5qSoOBqqpx4mN7SZERMCOdZfAEMBsQL004,6098
|
|
7
|
-
corelp/modules/Section_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
corelp/modules/Section_LP/test_Section.py,sha256=zcrIbJueMDT90t0_M-RD40IWpkx4OT7Q52tE6HzbfIo,812
|
|
5
|
+
corelp/modules/Path_LP/test_Path.py,sha256=E4m0n4aEaS0_KCNNpOxqnCQpiapHv3uAIaJSWwXpSY0,708
|
|
9
6
|
corelp/modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
7
|
corelp/modules/debug_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
8
|
corelp/modules/debug_LP/debug.py,sha256=Mkn3WPTkaKSXdfmY8ioEwu4OXQqiDoM2Akhbz62Nnis,1623
|
|
@@ -18,32 +15,23 @@ corelp/modules/getmodule_LP/getmodule.py,sha256=7I4ehsBtgfi-wUyiQ5eT07lc8FiUVN7F
|
|
|
18
15
|
corelp/modules/kwargsself_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
16
|
corelp/modules/kwargsself_LP/kwargsself.py,sha256=24HVn1G7ALdhQFSLT0U2dVjVzop6c2s-nr7DrMK53iw,1865
|
|
20
17
|
corelp/modules/kwargsself_LP/test_kwargsself.py,sha256=BaqGu0bqFuFemiYUEDMviFfegTb0aF6lmeFm3KJa8sw,1241
|
|
21
|
-
corelp/modules/main_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
|
-
corelp/modules/main_LP/main.py,sha256=4-sUPwKJkzcSwjHa4AzzH0-GRm0Z2N2_-5SZf2jhLOQ,10063
|
|
23
|
-
corelp/modules/main_LP/test_main.py,sha256=mxL645pZdkJ8J5MFdj0K-z8xRCGKQ0zw1NvmW3iPGB4,1741
|
|
24
|
-
corelp/modules/print_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
|
-
corelp/modules/print_LP/print.py,sha256=TXnxPc4bHf6zSaQkHJ-3iQNkERCG7hvb-tmCAgp94r0,8980
|
|
26
|
-
corelp/modules/print_LP/test_print.py,sha256=uMmCrnyIVSlZg_ZEOk2mr5zDlEpTN2KMq4jFu5p6n4I,2292
|
|
27
18
|
corelp/modules/prop_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
19
|
corelp/modules/prop_LP/prop.py,sha256=lfsENmjg65mpXxt9V9n3Nn__wHgNJA61l8_UXBKn1lc,3999
|
|
29
20
|
corelp/modules/prop_LP/test_prop.py,sha256=X5GJwIyik5Gzd6Z28h1kGdZzVVhb1D5FXTHXvXBbwfA,2302
|
|
30
21
|
corelp/modules/rfrom_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
22
|
corelp/modules/rfrom_LP/rfrom.py,sha256=f5-zPUUxlxInnaBM_WMuAaSMjdaoyOjsn5WbpLIfSVk,1690
|
|
32
|
-
corelp/modules/rfrom_LP/test_rfrom.py,sha256=
|
|
23
|
+
corelp/modules/rfrom_LP/test_rfrom.py,sha256=Sq9FeWnzpItiT8RGh6CzCdMnoZm4e2-dbkTs6dW2XPY,666
|
|
33
24
|
corelp/modules/selfkwargs_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
25
|
corelp/modules/selfkwargs_LP/selfkwargs.py,sha256=7yWkpVQRwb2VnDPUGxREXjyVIn0n8RpptlP3lnP57wU,1203
|
|
35
26
|
corelp/modules/selfkwargs_LP/test_selfkwargs.py,sha256=Ex-y60W9oD1OUtDlRvyxn-Wlq1l3JmIJY0Iot2uGQbY,826
|
|
36
27
|
corelp/modules/test_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
28
|
corelp/modules/test_LP/test.py,sha256=KwAeIZWQ7pZX85J50q6qfB4HuJUgREu1ieB_byPqI2g,1361
|
|
38
29
|
corelp/modules/test_LP/test_test.py,sha256=sXI6G4OBnWXSqrfMy9QdabkYIvcD80EmnNcnQiXxcRI,605
|
|
39
|
-
corelp/modules
|
|
40
|
-
corelp/modules/user_inputs_LP/test_user_inputs.py,sha256=-6YzBomJxIZSfnfbJPvnfgon3K5RTC3WQKNT4enpVH0,947
|
|
41
|
-
corelp/modules/user_inputs_LP/user_inputs.py,sha256=ochRTY892XwYANBRyP-kwR_-7S96AVF4fIhfe6P4t1c,2472
|
|
42
|
-
corelp/modules.json,sha256=ZQ8BMU8X2u71wfVj_AufwOoJUPdaxU_AHn7Ohbkp-Pc,3122
|
|
30
|
+
corelp/modules.json,sha256=3zREFn0--UhICcQJQG8syet8Ni1HdsG_pN0K86SQiXo,2230
|
|
43
31
|
corelp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
44
32
|
corelp/pythonLP.png:Zone.Identifier,sha256=uVLSTPcBvE56fSHhroXGEYJOgFeaiYNsDLSbGTRGzP4,25
|
|
45
33
|
corelp/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
34
|
corelp/scripts.json,sha256=RBNvo1WzZ4oRRq0W9-hknpT7T8If536DEMBg9hyq_4o,2
|
|
47
|
-
corelp-1.0.
|
|
48
|
-
corelp-1.0.
|
|
49
|
-
corelp-1.0.
|
|
35
|
+
corelp-1.0.38.dist-info/WHEEL,sha256=eycQt0QpYmJMLKpE3X9iDk8R04v2ZF0x82ogq-zP6bQ,79
|
|
36
|
+
corelp-1.0.38.dist-info/METADATA,sha256=I0RpZ1oe4qOcO5R7WAHrjHSYNmmqKVbhFEBy7bgufpA,1656
|
|
37
|
+
corelp-1.0.38.dist-info/RECORD,,
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# Date : 2025-08-28
|
|
4
|
-
# Author : Lancelot PINCET
|
|
5
|
-
# GitHub : https://github.com/LancelotPincet
|
|
6
|
-
# Library : coreLP
|
|
7
|
-
# Module : Section
|
|
8
|
-
|
|
9
|
-
"""
|
|
10
|
-
This class defines decorator instances allowing to create section functions.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
# %% Libraries
|
|
16
|
-
from corelp import print, folder, selfkwargs, kwargsself
|
|
17
|
-
from dataclasses import dataclass
|
|
18
|
-
import pickle
|
|
19
|
-
import joblib
|
|
20
|
-
from pathlib import Path
|
|
21
|
-
from functools import wraps
|
|
22
|
-
import hashlib
|
|
23
|
-
import inspect
|
|
24
|
-
import os
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
# %% Class
|
|
29
|
-
@dataclass(slots=True, kw_only=True)
|
|
30
|
-
class Section() :
|
|
31
|
-
'''
|
|
32
|
-
This class defines decorator instances allowing to create section functions.
|
|
33
|
-
Cache results into a folder, if another call occurs, can load-back the precalculated data.
|
|
34
|
-
|
|
35
|
-
Parameters
|
|
36
|
-
----------
|
|
37
|
-
path : str or Path
|
|
38
|
-
path where to save section folder results.
|
|
39
|
-
new : bool
|
|
40
|
-
True to ignore pre-calculated data and crush them.
|
|
41
|
-
num : int
|
|
42
|
-
Index of section, after one call, adds 1 for next call.
|
|
43
|
-
parent_path : str or Path
|
|
44
|
-
Path to the parent folder if bulk processing.
|
|
45
|
-
|
|
46
|
-
Examples
|
|
47
|
-
--------
|
|
48
|
-
>>> from corelp import Section
|
|
49
|
-
...
|
|
50
|
-
>>> section = Section(path=export_path)
|
|
51
|
-
...
|
|
52
|
-
>>> @section()
|
|
53
|
-
... def add(a, b=0) :
|
|
54
|
-
... testfunc.print('Hello World')
|
|
55
|
-
... return a + b
|
|
56
|
-
...
|
|
57
|
-
>>> testfunc.print('3+0=', add(3)) # First call calculates and save result
|
|
58
|
-
>>> testfunc.print('3+0=', add(3, 0)) # Second call loads back precalculated results
|
|
59
|
-
>>> testfunc.print('1+3=', add(1, 3)) # New call with other parameters : crushed previous results with new ones
|
|
60
|
-
>>> testfunc.print('1+3=', add(1, b=3)) # Second call with these parameters : loads precalculated results
|
|
61
|
-
...
|
|
62
|
-
>>> @section(cache=False) # Creates an index of 2, does no caching
|
|
63
|
-
... def sub(a, b=0) :
|
|
64
|
-
... return a - b
|
|
65
|
-
...
|
|
66
|
-
>>> @section(num=10) # Creates an index of 10
|
|
67
|
-
... def mul(a, b=0) :
|
|
68
|
-
... return a * b
|
|
69
|
-
...
|
|
70
|
-
>>> @section(new=True) # Creates an index of 11, always creates new cache
|
|
71
|
-
... def div(a, b) :
|
|
72
|
-
... return a / b
|
|
73
|
-
'''
|
|
74
|
-
|
|
75
|
-
# Attributes
|
|
76
|
-
path : Path | str = None
|
|
77
|
-
new :bool = False
|
|
78
|
-
num :int = 0
|
|
79
|
-
parent_path : Path | str = None
|
|
80
|
-
|
|
81
|
-
# Init
|
|
82
|
-
def __post_init__(self) :
|
|
83
|
-
if self.path is not None :
|
|
84
|
-
self.path = Path(self.path)
|
|
85
|
-
if self.parent_path is not None :
|
|
86
|
-
self.parent_path = Path(self.parent_path)
|
|
87
|
-
|
|
88
|
-
# Decorator
|
|
89
|
-
def __call__(self, *, new=None, num=None, symlink=None, cache=True):
|
|
90
|
-
if new is None :
|
|
91
|
-
new = self.new
|
|
92
|
-
if num is None :
|
|
93
|
-
num = self.num
|
|
94
|
-
self.num = num+1
|
|
95
|
-
|
|
96
|
-
def decorator(func) :
|
|
97
|
-
name = func.__name__
|
|
98
|
-
|
|
99
|
-
@wraps(func)
|
|
100
|
-
def wrapper(*args, **kwargs):
|
|
101
|
-
wrapper.path = self.path / f"{num:03}_{name}"
|
|
102
|
-
print(f'\n#### **{num}. {name.replace("_"," ")} section**\n')
|
|
103
|
-
|
|
104
|
-
# Creating hash
|
|
105
|
-
if cache :
|
|
106
|
-
print('**Call hash:**', do_stdout=False)
|
|
107
|
-
bound = inspect.signature(func).bind(*args, **kwargs)
|
|
108
|
-
bound.apply_defaults()
|
|
109
|
-
serialized = pickle.dumps(bound.arguments)
|
|
110
|
-
args_hash = hashlib.md5(serialized).hexdigest()
|
|
111
|
-
result_file = wrapper.path / f'{args_hash}.pkl'
|
|
112
|
-
print(f'*{args_hash}*\n', do_stdout=False)
|
|
113
|
-
|
|
114
|
-
# Checking already calculated exists
|
|
115
|
-
if result_file.exists() and not new :
|
|
116
|
-
print('**Loading from *precalculated* results...**')
|
|
117
|
-
with open(result_file, 'rb') as f:
|
|
118
|
-
result = joblib.load(f)
|
|
119
|
-
print('...loaded\n')
|
|
120
|
-
return result
|
|
121
|
-
|
|
122
|
-
# Calculations
|
|
123
|
-
folder(wrapper.path, warning=False)
|
|
124
|
-
print('**Calculating results:**')
|
|
125
|
-
print_status = kwargsself(print)
|
|
126
|
-
print.file = wrapper.path / f'{name}_log.md'
|
|
127
|
-
result = func(*args, **kwargs)
|
|
128
|
-
selfkwargs(print, print_status)
|
|
129
|
-
print('...calculated\n')
|
|
130
|
-
|
|
131
|
-
# Caching
|
|
132
|
-
if cache :
|
|
133
|
-
print('**Saving results:**')
|
|
134
|
-
with open(result_file, 'wb') as f:
|
|
135
|
-
joblib.dump(result, f)
|
|
136
|
-
print('...saved\n')
|
|
137
|
-
|
|
138
|
-
# Create symlink
|
|
139
|
-
if symlink is not None :
|
|
140
|
-
print('**Creating symlinks:**')
|
|
141
|
-
for link in symlink :
|
|
142
|
-
print(f"- {link}")
|
|
143
|
-
link_path = Path(link)
|
|
144
|
-
link_folder = self.parent_path.parent / f'_outputs/{link_path.stem}'
|
|
145
|
-
new_stem = str(self.subfolder.as_posix()).replace('/', '--').replace(' ', '_')
|
|
146
|
-
if not link_folder.exists() :
|
|
147
|
-
folder(link_folder, warning=False)
|
|
148
|
-
link_from = wrapper.path / link_path
|
|
149
|
-
link_to = link_folder / f"{new_stem}{link_path.suffix}"
|
|
150
|
-
if link_to.exists() or link_to.is_symlink():
|
|
151
|
-
link_to.unlink()
|
|
152
|
-
if os.name == "nt":
|
|
153
|
-
try :
|
|
154
|
-
link_to.symlink_to(link_from, link_from.is_dir())
|
|
155
|
-
except OSError :
|
|
156
|
-
print("Windows does not allow to create symlink, aborting. Consider using Windows in Developper mode.")
|
|
157
|
-
break
|
|
158
|
-
else:
|
|
159
|
-
link_to.symlink_to(link_from)
|
|
160
|
-
print('...created\n')
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
return result
|
|
164
|
-
return wrapper
|
|
165
|
-
return decorator
|
|
166
|
-
|
|
167
|
-
@property
|
|
168
|
-
def subfolder(self) :
|
|
169
|
-
return self.path.relative_to(self.parent_path)
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
# %% Test function run
|
|
174
|
-
if __name__ == "__main__":
|
|
175
|
-
from corelp import test
|
|
176
|
-
test(__file__)
|
|
File without changes
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# Date : 2025-08-28
|
|
4
|
-
# Author : Lancelot PINCET
|
|
5
|
-
# GitHub : https://github.com/LancelotPincet
|
|
6
|
-
# Library : coreLP
|
|
7
|
-
# Module : Section
|
|
8
|
-
|
|
9
|
-
"""
|
|
10
|
-
This file allows to test Section
|
|
11
|
-
|
|
12
|
-
Section : This class defines decorator instances allowing to create section functions.
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# %% Libraries
|
|
18
|
-
from corelp import debug, Section
|
|
19
|
-
debug_folder = debug(__file__)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# %% Function test
|
|
24
|
-
def test_function() :
|
|
25
|
-
'''
|
|
26
|
-
Test Section function
|
|
27
|
-
'''
|
|
28
|
-
section = Section(path=debug_folder)
|
|
29
|
-
|
|
30
|
-
@section()
|
|
31
|
-
def add(a, b=0) :
|
|
32
|
-
return a+b
|
|
33
|
-
assert add(3) == 3
|
|
34
|
-
assert add(3, 0) == 3
|
|
35
|
-
assert add(1, 3) == 4
|
|
36
|
-
assert add(1, b=3) == 4
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
# %% Test function run
|
|
41
|
-
if __name__ == "__main__":
|
|
42
|
-
from corelp import test
|
|
43
|
-
test(__file__)
|
|
File without changes
|
corelp/modules/main_LP/main.py
DELETED
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# Date : 2025-08-28
|
|
4
|
-
# Author : Lancelot PINCET
|
|
5
|
-
# GitHub : https://github.com/LancelotPincet
|
|
6
|
-
# Library : coreLP
|
|
7
|
-
# Module : main
|
|
8
|
-
|
|
9
|
-
"""
|
|
10
|
-
This function can decorate the main function of a script.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
# %% Libraries
|
|
16
|
-
from corelp import print, Section, folder, selfkwargs, kwargsself, icon, Path
|
|
17
|
-
import time
|
|
18
|
-
import functools
|
|
19
|
-
import os
|
|
20
|
-
from datetime import datetime
|
|
21
|
-
import tkinter as tk
|
|
22
|
-
from tkinter import filedialog
|
|
23
|
-
import types
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
# %% Function
|
|
28
|
-
def main() :
|
|
29
|
-
'''
|
|
30
|
-
This function can decorate the main function of a script.
|
|
31
|
-
User inputs parameters shoud be put in the beginning of the main file, and the decorated function will recognize them.
|
|
32
|
-
Decorated function can change the values of these parameters with keyword arguments when called.
|
|
33
|
-
Section can be created bellow the mainfunction.
|
|
34
|
-
|
|
35
|
-
Global parameters
|
|
36
|
-
-----------------
|
|
37
|
-
import_path : Path or str or None
|
|
38
|
-
Path where to import script data to process.
|
|
39
|
-
If None, will manually ask user to select it.
|
|
40
|
-
If not existent, will be ignored.
|
|
41
|
-
export_path : Path or str or None
|
|
42
|
-
Path where to export script data to process.
|
|
43
|
-
A new folder will be created inside at the call time as name.
|
|
44
|
-
If None, will save in import_path. If not existent, will be ignored.
|
|
45
|
-
If a previous call was already made in this same folder, and new is False, will try to reload data from this last folder.
|
|
46
|
-
new : bool
|
|
47
|
-
Overrides Decorator new parameter.
|
|
48
|
-
bulk : function
|
|
49
|
-
function(import_path) that returns a dictionnary of {import_subfolder:export_subfolder} for multiple decorated function run.
|
|
50
|
-
If bulk is not None, the decorated function will run with import_subfolder, export_subfolder instead of import_path, export_path (see below).
|
|
51
|
-
The import_subfolders and export_subfolder are defined from import_path and export_path respectively (they are not absolute from root path).
|
|
52
|
-
overnight : bool
|
|
53
|
-
If True and exception occurs, will skip and pass to the next run in bulk processing. To use for example for overnight bulk processing.
|
|
54
|
-
|
|
55
|
-
Examples
|
|
56
|
-
--------
|
|
57
|
-
>>> from corelp import main
|
|
58
|
-
...
|
|
59
|
-
>>> import_path = None # will be asked via a GUI
|
|
60
|
-
>>> export_path = None # will create inside import_path
|
|
61
|
-
>>> new = False # True to create a new export folder, False to reload precalculated data
|
|
62
|
-
>>> bulk = None # function(import_path) that returns a dictionnary of {import_subfolder:export_subfolder} for multiple decorated function run.
|
|
63
|
-
>>> overnight= False # If True and exception occurs, will skip and pass to the next run in bulk processing.
|
|
64
|
-
>>> main_string = "Hello from main!" # User input parameter
|
|
65
|
-
...
|
|
66
|
-
>>> @main(new=True) # if previous new is not defined, new is defined here
|
|
67
|
-
... def myscript() :
|
|
68
|
-
... print(main_string) # By default prints "Hello from main!"
|
|
69
|
-
... result = mysection() # Section defined bellow, result can be reloaded from previous run
|
|
70
|
-
... return result
|
|
71
|
-
...
|
|
72
|
-
... @main.section()
|
|
73
|
-
... def mysection() :
|
|
74
|
-
... print("Hello from section!")
|
|
75
|
-
... return True # Will be saved into export_path and can be reuploaded at next run with same inputs
|
|
76
|
-
...
|
|
77
|
-
>>> # Launch
|
|
78
|
-
>>> if __name__ == "__main__" :
|
|
79
|
-
... myscript() # prints "Hello from main!"
|
|
80
|
-
... myscript(main_string = "Hello changed!!") # prints "Hello changed!!" and loads section result from first run
|
|
81
|
-
'''
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def decorator(func) :
|
|
86
|
-
name = func.__name__
|
|
87
|
-
|
|
88
|
-
# Get globals around function definition
|
|
89
|
-
definition_globals = func.__globals__
|
|
90
|
-
|
|
91
|
-
@functools.wraps(func)
|
|
92
|
-
def wrapper(**overrides) -> None :
|
|
93
|
-
|
|
94
|
-
# Creates new globals
|
|
95
|
-
exec_globals = definition_globals.copy()
|
|
96
|
-
exec_globals.update(overrides)
|
|
97
|
-
_new = exec_globals.get("new", False)
|
|
98
|
-
_bulk = exec_globals.get("bulk", None)
|
|
99
|
-
_overnight = exec_globals.get("overnight", False)
|
|
100
|
-
|
|
101
|
-
# Creates new function
|
|
102
|
-
new_func = types.FunctionType(
|
|
103
|
-
func.__code__,
|
|
104
|
-
exec_globals,
|
|
105
|
-
name=name,
|
|
106
|
-
argdefs=func.__defaults__,
|
|
107
|
-
closure=func.__closure__,
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
# Getting paths
|
|
111
|
-
ipath = exec_globals.get('import_path', "None")
|
|
112
|
-
if ipath is None :
|
|
113
|
-
root = tk.Tk()
|
|
114
|
-
root.title("Select import path")
|
|
115
|
-
img = tk.PhotoImage(file=icon)
|
|
116
|
-
root.iconphoto(True, img)
|
|
117
|
-
root._icon_img = img # keep reference
|
|
118
|
-
root.withdraw()
|
|
119
|
-
root.update_idletasks()
|
|
120
|
-
root.attributes("-topmost", True)
|
|
121
|
-
root.update()
|
|
122
|
-
root.focus_force()
|
|
123
|
-
ipath = filedialog.askdirectory(title=f'Select import path for {name}')
|
|
124
|
-
root.destroy()
|
|
125
|
-
if not ipath :
|
|
126
|
-
print('Searching for import_path was cancelled', style='red')
|
|
127
|
-
raise ValueError('Searching for import_path was cancelled')
|
|
128
|
-
epath = exec_globals.get('export_path', "None")
|
|
129
|
-
if ipath != "None" :
|
|
130
|
-
ipath = Path(ipath)
|
|
131
|
-
if epath != "None" :
|
|
132
|
-
epath = ipath.parent if epath is None else Path(epath)
|
|
133
|
-
|
|
134
|
-
# Creating new export path
|
|
135
|
-
prefix = name.replace('.', '_')
|
|
136
|
-
if epath != "None" :
|
|
137
|
-
if _new :
|
|
138
|
-
base_path = folder(epath / (f'{prefix}_' + datetime.now().strftime("%Y-%m-%d-%Hh%Mmin%Ss")), warning=False)
|
|
139
|
-
else :
|
|
140
|
-
#Searching for newest old folder
|
|
141
|
-
base_folder = None
|
|
142
|
-
_date = None
|
|
143
|
-
for f in epath.iterdir() :
|
|
144
|
-
if (not f.is_dir()) or (not f.name.startswith(f'{prefix}_')) :
|
|
145
|
-
continue
|
|
146
|
-
date_str = f.name.split('_')[-1]
|
|
147
|
-
date = datetime.strptime(date_str, "%Y-%m-%d-%Hh%Mmin%Ss")
|
|
148
|
-
if _date is None or date > _date :
|
|
149
|
-
_date, base_folder = date, f
|
|
150
|
-
base_path = base_folder if base_folder is not None else epath / (f'{prefix}_' + datetime.now().strftime("%Y-%m-%d-%Hh%Mmin%Ss"))
|
|
151
|
-
epath = base_path / 'export_folder'
|
|
152
|
-
if not epath.exists():
|
|
153
|
-
os.makedirs(epath) #creates folders until end
|
|
154
|
-
if ipath != "None" :
|
|
155
|
-
ilink = base_path / 'import_folder'
|
|
156
|
-
if ilink.exists() or ilink.is_symlink():
|
|
157
|
-
ilink.unlink()
|
|
158
|
-
if os.name == "nt":
|
|
159
|
-
try :
|
|
160
|
-
ilink.symlink_to(ipath, ipath.is_dir())
|
|
161
|
-
except OSError :
|
|
162
|
-
print("Windows does not allow to create symlink, aborting. Consider using Windows in Developper mode.")
|
|
163
|
-
else:
|
|
164
|
-
ilink.symlink_to(ipath)
|
|
165
|
-
md_file = epath / (name+'_log.md')
|
|
166
|
-
html_file = epath / (name+'_log.html')
|
|
167
|
-
else :
|
|
168
|
-
md_file = None
|
|
169
|
-
html_file = None
|
|
170
|
-
|
|
171
|
-
# Defining bulk processing
|
|
172
|
-
if _bulk is None :
|
|
173
|
-
subfolders = {"" : ""}
|
|
174
|
-
else :
|
|
175
|
-
subfolders = _bulk(ipath)
|
|
176
|
-
|
|
177
|
-
#Begining prints
|
|
178
|
-
print_status = kwargsself(print)
|
|
179
|
-
print.console = None
|
|
180
|
-
print.file = md_file
|
|
181
|
-
print(f'\n\n\n# **BEGIN {name}\n**')
|
|
182
|
-
print(f"{time.ctime()}")
|
|
183
|
-
if ipath != "None" :
|
|
184
|
-
print(f'import_path : {ipath}\n')
|
|
185
|
-
if epath != "None" :
|
|
186
|
-
print(f'export_path : {epath}\n')
|
|
187
|
-
|
|
188
|
-
# Bulk processing
|
|
189
|
-
results = {} # {export_subfolder : fucntion result}
|
|
190
|
-
for import_subfolder, export_subfolder in subfolders.items() :
|
|
191
|
-
if ipath != "None" :
|
|
192
|
-
impath = ipath / import_subfolder
|
|
193
|
-
exec_globals["import_path"] = impath
|
|
194
|
-
if epath != "None" :
|
|
195
|
-
expath = epath / export_subfolder
|
|
196
|
-
exec_globals["export_path"] = expath
|
|
197
|
-
|
|
198
|
-
# Create export subfolder
|
|
199
|
-
if not expath.exists() :
|
|
200
|
-
os.mkdir(expath)
|
|
201
|
-
|
|
202
|
-
# Updating sections
|
|
203
|
-
wrapper.section.parent_path = epath
|
|
204
|
-
wrapper.section.path = expath
|
|
205
|
-
wrapper.section.new = _new
|
|
206
|
-
|
|
207
|
-
#Applying function
|
|
208
|
-
print("\n---\n")
|
|
209
|
-
subfolder_string = f"{export_subfolder}" if export_subfolder != "" else ""
|
|
210
|
-
print(f'## **Launched script {subfolder_string}**\n')
|
|
211
|
-
tic = time.perf_counter()
|
|
212
|
-
try :
|
|
213
|
-
results[export_subfolder] = new_func()
|
|
214
|
-
|
|
215
|
-
# Errors
|
|
216
|
-
except Exception as e :
|
|
217
|
-
toc = time.perf_counter()
|
|
218
|
-
print.error()
|
|
219
|
-
print(f'\n## **{subfolder_string} took {toc-tic:.2f}s**')
|
|
220
|
-
print("\n---\n")
|
|
221
|
-
if not _overnight :
|
|
222
|
-
raise e
|
|
223
|
-
|
|
224
|
-
# No error
|
|
225
|
-
else :
|
|
226
|
-
toc = time.perf_counter()
|
|
227
|
-
print(f'\n## **{subfolder_string} took {toc-tic:.2f}s**')
|
|
228
|
-
print("\n---\n")
|
|
229
|
-
|
|
230
|
-
# END
|
|
231
|
-
print(time.ctime())
|
|
232
|
-
print(f'# **END {name}**\n\n')
|
|
233
|
-
print.export_html(html_file)
|
|
234
|
-
selfkwargs(print, print_status)
|
|
235
|
-
if _bulk is None :
|
|
236
|
-
results = results[""]
|
|
237
|
-
return results
|
|
238
|
-
|
|
239
|
-
# Making sections
|
|
240
|
-
section = Section()
|
|
241
|
-
wrapper.section = section
|
|
242
|
-
|
|
243
|
-
return wrapper
|
|
244
|
-
return decorator
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
# %% Test function run
|
|
249
|
-
if __name__ == "__main__":
|
|
250
|
-
from corelp import test
|
|
251
|
-
test(__file__)
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# Date : 2025-08-28
|
|
4
|
-
# Author : Lancelot PINCET
|
|
5
|
-
# GitHub : https://github.com/LancelotPincet
|
|
6
|
-
# Library : coreLP
|
|
7
|
-
# Module : main
|
|
8
|
-
|
|
9
|
-
"""
|
|
10
|
-
This file allows to test main
|
|
11
|
-
|
|
12
|
-
main : This function can decorate the main function of a script.
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# %% Libraries
|
|
18
|
-
from corelp import print, debug, main
|
|
19
|
-
from time import sleep
|
|
20
|
-
import pytest
|
|
21
|
-
debug_folder = debug(__file__)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
# %% User inputs
|
|
26
|
-
search = False # True to apply manual search
|
|
27
|
-
global import_path
|
|
28
|
-
global export_path
|
|
29
|
-
import_path = None if search else debug_folder # Path to the imported data
|
|
30
|
-
export_path = import_path # Path to the exported data
|
|
31
|
-
new = False # True to create new result folder at each run
|
|
32
|
-
bulk = None # function(import_path) that returns a dictionnary of {import_subfolder:export_subfolder} for multiple decorated function run.
|
|
33
|
-
overnight= False # If True and exception occurs, will skip and pass to the next run in bulk processing.
|
|
34
|
-
myparam = "Hello from main!"
|
|
35
|
-
apply_error = False
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
@main()
|
|
40
|
-
def mainfunc() :
|
|
41
|
-
if apply_error :
|
|
42
|
-
1/0
|
|
43
|
-
print(myparam)
|
|
44
|
-
result = section_1()
|
|
45
|
-
print(f"import_path = {import_path}")
|
|
46
|
-
return result
|
|
47
|
-
|
|
48
|
-
@mainfunc.section()
|
|
49
|
-
def section_1() :
|
|
50
|
-
print('> Hello from section!')
|
|
51
|
-
return True
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
# %% Function test
|
|
56
|
-
def test_function() :
|
|
57
|
-
'''
|
|
58
|
-
Test main function
|
|
59
|
-
'''
|
|
60
|
-
mainfunc()
|
|
61
|
-
sleep(2) # Ensure new folder
|
|
62
|
-
mainfunc(myparam="Hello changed!!")
|
|
63
|
-
sleep(2) # Ensure new folder
|
|
64
|
-
mainfunc(new=True)
|
|
65
|
-
sleep(2) # Ensure new folder
|
|
66
|
-
with pytest.raises(ZeroDivisionError, match="division by zero") :
|
|
67
|
-
mainfunc(apply_error=True)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
# %% Test function run
|
|
72
|
-
if __name__ == "__main__":
|
|
73
|
-
from corelp import test
|
|
74
|
-
test(__file__)
|
|
File without changes
|
corelp/modules/print_LP/print.py
DELETED
|
@@ -1,326 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# Date : 2025-08-27
|
|
4
|
-
# Author : Lancelot PINCET
|
|
5
|
-
# GitHub : https://github.com/LancelotPincet
|
|
6
|
-
# Library : coreLP
|
|
7
|
-
# Module : print
|
|
8
|
-
|
|
9
|
-
"""
|
|
10
|
-
This function overrides python built in print function to add functionnalities.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
# %% Libraries
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# %% Libraries
|
|
20
|
-
from corelp import prop
|
|
21
|
-
from dataclasses import dataclass, field
|
|
22
|
-
from datetime import datetime, timedelta
|
|
23
|
-
from numpy._core.numeric import True_
|
|
24
|
-
from rich import print as richprint
|
|
25
|
-
from rich.console import Console
|
|
26
|
-
from rich.theme import Theme
|
|
27
|
-
from rich.markdown import Markdown
|
|
28
|
-
from rich.traceback import Traceback
|
|
29
|
-
from rich.progress import (
|
|
30
|
-
Progress,
|
|
31
|
-
BarColumn,
|
|
32
|
-
TextColumn,
|
|
33
|
-
TaskProgressColumn,
|
|
34
|
-
TimeElapsedColumn,
|
|
35
|
-
TimeRemainingColumn,
|
|
36
|
-
ProgressColumn,
|
|
37
|
-
)
|
|
38
|
-
import traceback as tb_module
|
|
39
|
-
from time import perf_counter
|
|
40
|
-
from pathlib import Path
|
|
41
|
-
pyprint = print
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
# %% Class
|
|
46
|
-
@dataclass(slots=True, kw_only=True)
|
|
47
|
-
class Print() :
|
|
48
|
-
r"""
|
|
49
|
-
Enhanced replacement for the built-in :func:`print` function, adding muting,
|
|
50
|
-
logging, rich formatting, and progress utilities.
|
|
51
|
-
|
|
52
|
-
This class is callable and behaves like :func:`print`, with extra arguments.
|
|
53
|
-
|
|
54
|
-
Parameters
|
|
55
|
-
----------
|
|
56
|
-
*strings : tuple
|
|
57
|
-
The objects to print. Its :meth:`__str__` representation is used.
|
|
58
|
-
verbose : bool, optional
|
|
59
|
-
If ``True`` (default), printing is performed.
|
|
60
|
-
If ``False``, printing is skipped unless overridden.
|
|
61
|
-
return_string : bool, optional
|
|
62
|
-
If ``True``, return the processed string instead of ``None``.
|
|
63
|
-
file : str or pathlib.Path or None, optional
|
|
64
|
-
If provided, overrides the configured log file.
|
|
65
|
-
mode : {"w", "a"}, optional
|
|
66
|
-
File mode used when writing logs. Default is ``"a"``.
|
|
67
|
-
end : str, optional
|
|
68
|
-
End-of-line character(s). Defaults to ``"\n"``.
|
|
69
|
-
**kwargs :
|
|
70
|
-
Additional keyword arguments passed to :func:`print` or Rich's :func:`Console.print`.
|
|
71
|
-
|
|
72
|
-
Examples
|
|
73
|
-
--------
|
|
74
|
-
Basic usage::
|
|
75
|
-
|
|
76
|
-
>>> from corelp import print
|
|
77
|
-
>>> s = "Hello *world*!\nThis is a print **example**"
|
|
78
|
-
>>> print(s)
|
|
79
|
-
|
|
80
|
-
Muting::
|
|
81
|
-
|
|
82
|
-
>>> print.verbose = False
|
|
83
|
-
>>> print(s) # muted
|
|
84
|
-
>>> print(s, verbose=True) # forced printing
|
|
85
|
-
>>> print.verbose = True
|
|
86
|
-
>>> print(s) # prints again
|
|
87
|
-
>>> print(s, verbose=False) # forced mute
|
|
88
|
-
|
|
89
|
-
Access to underlying print functions::
|
|
90
|
-
|
|
91
|
-
>>> print.pyprint(s) # built-in print
|
|
92
|
-
>>> print.richprint(s) # rich.print
|
|
93
|
-
>>> print.print(s) # Console.print
|
|
94
|
-
>>> print.log(s) # Console.log
|
|
95
|
-
|
|
96
|
-
Logging::
|
|
97
|
-
|
|
98
|
-
>>> print.file = "log.txt"
|
|
99
|
-
>>> print("Hello") # also writes to file
|
|
100
|
-
|
|
101
|
-
Console styling::
|
|
102
|
-
|
|
103
|
-
>>> print.theme = {"success": "green"}
|
|
104
|
-
>>> print("Done!", style="success")
|
|
105
|
-
>>> try:
|
|
106
|
-
... 1/0
|
|
107
|
-
... except Exception:
|
|
108
|
-
... print.error()
|
|
109
|
-
>>> print.export_html("log.html")
|
|
110
|
-
|
|
111
|
-
Progress / Clock::
|
|
112
|
-
|
|
113
|
-
>>> from time import sleep
|
|
114
|
-
>>> for i in print.clock(15, "Outer"):
|
|
115
|
-
... for j in print.clock(10, "Inner"):
|
|
116
|
-
... sleep(1)
|
|
117
|
-
|
|
118
|
-
Attributes
|
|
119
|
-
----------
|
|
120
|
-
verbose : bool
|
|
121
|
-
Global muting switch.
|
|
122
|
-
pyprint : callable
|
|
123
|
-
Built-in Python :func:`print`.
|
|
124
|
-
richprint : callable
|
|
125
|
-
:mod:`rich` print function.
|
|
126
|
-
console : rich.console.Console
|
|
127
|
-
The Rich console instance used for styled printing.
|
|
128
|
-
file : pathlib.Path or None
|
|
129
|
-
Path to the log file.
|
|
130
|
-
progress : rich.progress.Progress
|
|
131
|
-
Active Rich progress manager.
|
|
132
|
-
bars : dict
|
|
133
|
-
Dictionary storing active progress bars.
|
|
134
|
-
theme : dict
|
|
135
|
-
Custom Rich style definitions.
|
|
136
|
-
"""
|
|
137
|
-
|
|
138
|
-
# Main function
|
|
139
|
-
def __call__(self, *strings, verbose=None, do_stdout=True, do_file=True, return_string=False, file=None, mode='a', end='\n', **kwargs) :
|
|
140
|
-
|
|
141
|
-
# Muting
|
|
142
|
-
verbose = verbose if verbose is not None else self.verbose
|
|
143
|
-
if not verbose :
|
|
144
|
-
return None
|
|
145
|
-
|
|
146
|
-
# Formatting string
|
|
147
|
-
string = ", ".join([str(string) for string in strings]) + end
|
|
148
|
-
|
|
149
|
-
# Printing markdown
|
|
150
|
-
if do_stdout :
|
|
151
|
-
string2print = Markdown(string) if self.apply_markdown else string
|
|
152
|
-
self.print(string2print, **kwargs)
|
|
153
|
-
|
|
154
|
-
# Writting to file
|
|
155
|
-
if do_file :
|
|
156
|
-
file = file if file is not None else self.file
|
|
157
|
-
if file is not None :
|
|
158
|
-
with open(Path(file), mode) as file :
|
|
159
|
-
file.write(string)
|
|
160
|
-
|
|
161
|
-
# Return
|
|
162
|
-
if return_string :
|
|
163
|
-
return string
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
# MUTING
|
|
167
|
-
verbose : bool = True # True to print
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
# PRINT
|
|
172
|
-
|
|
173
|
-
@property
|
|
174
|
-
def print(self) :
|
|
175
|
-
return self.console.print
|
|
176
|
-
@property
|
|
177
|
-
def log(self) :
|
|
178
|
-
return self.console.log
|
|
179
|
-
pyprint = pyprint # python print
|
|
180
|
-
richprint = richprint # rich prints
|
|
181
|
-
apply_markdown : bool = field(default=True, repr=False) # True to apply rich markdown formatting in prints
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
# LOGGING
|
|
186
|
-
|
|
187
|
-
_file : Path = None
|
|
188
|
-
@property
|
|
189
|
-
def file(self) :
|
|
190
|
-
return self._file
|
|
191
|
-
@file.setter
|
|
192
|
-
def file(self, value) :
|
|
193
|
-
self._file = Path(value)
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
# CONSOLE
|
|
198
|
-
|
|
199
|
-
_theme = {}
|
|
200
|
-
@property
|
|
201
|
-
def theme(self) :
|
|
202
|
-
return self._theme
|
|
203
|
-
@theme.setter
|
|
204
|
-
def theme(self, value) :
|
|
205
|
-
self._theme.update(value)
|
|
206
|
-
self._console = None
|
|
207
|
-
|
|
208
|
-
_console : Console = field(default=None, repr=False)
|
|
209
|
-
@prop(cache=True)
|
|
210
|
-
def console(self) :
|
|
211
|
-
theme = Theme(self.theme)
|
|
212
|
-
return Console(theme=theme, record=True)
|
|
213
|
-
|
|
214
|
-
def error(self) :
|
|
215
|
-
rich_tb = Traceback.from_exception(*tb_module.sys.exc_info())
|
|
216
|
-
self.console.print(rich_tb)
|
|
217
|
-
|
|
218
|
-
def print_locals(self) :
|
|
219
|
-
self.console.log(log_locals=True)
|
|
220
|
-
|
|
221
|
-
def export_html(self, path) :
|
|
222
|
-
if path is None :
|
|
223
|
-
return
|
|
224
|
-
path = Path(path)
|
|
225
|
-
html_content = self.console.export_html(inline_styles=True)
|
|
226
|
-
with open(path, "w", encoding="utf-8") as file:
|
|
227
|
-
file.write(html_content)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
# CLOCK
|
|
232
|
-
|
|
233
|
-
def clock(self, iterable, title="Working...") :
|
|
234
|
-
|
|
235
|
-
# Get iterable
|
|
236
|
-
iterable = range(iterable) if isinstance(iterable, int) else iterable
|
|
237
|
-
iterable = list(iterable)
|
|
238
|
-
|
|
239
|
-
# Detect if progressbar already exists
|
|
240
|
-
first_bar = getattr(self, "_progress", None) is None
|
|
241
|
-
progress = self.progress
|
|
242
|
-
bars = self.bars
|
|
243
|
-
|
|
244
|
-
# Opens progress
|
|
245
|
-
if first_bar :
|
|
246
|
-
verbose = self.verbose
|
|
247
|
-
self.verbose = False
|
|
248
|
-
|
|
249
|
-
# Write to file
|
|
250
|
-
if self.file is not None :
|
|
251
|
-
with open(Path(self.file), "a") as file :
|
|
252
|
-
file.write(f'{title}...\n')
|
|
253
|
-
progress.start()
|
|
254
|
-
|
|
255
|
-
# Create new task
|
|
256
|
-
task = bars.get(title, None)
|
|
257
|
-
if task is None : # No bar with this name exists
|
|
258
|
-
task = progress.add_task(title, total=len(iterable), avg_time=0.0)
|
|
259
|
-
bars[title] = task # store it
|
|
260
|
-
else :
|
|
261
|
-
progress.reset(task)
|
|
262
|
-
|
|
263
|
-
# Loop
|
|
264
|
-
loop_counter = 0
|
|
265
|
-
start = perf_counter()
|
|
266
|
-
for item in iterable :
|
|
267
|
-
yield item
|
|
268
|
-
loop_counter += 1
|
|
269
|
-
elapsed = perf_counter() - start
|
|
270
|
-
avg_time = elapsed / loop_counter if loop_counter else 0
|
|
271
|
-
progress.update(task, advance=1, avg_time=avg_time)
|
|
272
|
-
|
|
273
|
-
# Clean up
|
|
274
|
-
if first_bar :
|
|
275
|
-
progress.stop()
|
|
276
|
-
del(self.bars)
|
|
277
|
-
del(self.progress)
|
|
278
|
-
self.verbose = verbose
|
|
279
|
-
|
|
280
|
-
_progress : Progress = field(default=None, repr=False)
|
|
281
|
-
@prop(cache=True)
|
|
282
|
-
def progress(self) :
|
|
283
|
-
return Progress(
|
|
284
|
-
TextColumn("{task.description}"),
|
|
285
|
-
BarColumn(),
|
|
286
|
-
TaskProgressColumn(),
|
|
287
|
-
TextColumn("[magenta]/{task.total}[/]"),
|
|
288
|
-
TimeElapsedColumn(),
|
|
289
|
-
AvgLoopTimeColumn(),
|
|
290
|
-
TimeRemainingColumn(),
|
|
291
|
-
EndTimeColumn(),
|
|
292
|
-
transient=False,
|
|
293
|
-
console=self.console
|
|
294
|
-
)
|
|
295
|
-
|
|
296
|
-
_bars : dict = field(default=None, repr=False)
|
|
297
|
-
@prop(cache=True)
|
|
298
|
-
def bars(self) :
|
|
299
|
-
return {}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
# Get instance
|
|
304
|
-
print = Print() # Instance to use everywhere
|
|
305
|
-
|
|
306
|
-
# Custom Progress bar columns
|
|
307
|
-
class AvgLoopTimeColumn(ProgressColumn):
|
|
308
|
-
def render(self, task):
|
|
309
|
-
avg_time = task.fields.get("avg_time", None)
|
|
310
|
-
if avg_time is not None and task.completed > 0:
|
|
311
|
-
string = f"[yellow]↻ {avg_time:.2f}s[/]" if avg_time > 1 else f"[yellow]↻ {avg_time*1000:.2f}ms[/]"
|
|
312
|
-
return string
|
|
313
|
-
return ""
|
|
314
|
-
class EndTimeColumn(ProgressColumn):
|
|
315
|
-
def render(self, task):
|
|
316
|
-
if task.time_remaining is not None:
|
|
317
|
-
end_time = datetime.now() + timedelta(seconds=task.time_remaining)
|
|
318
|
-
return f"[cyan]{end_time:%m-%d %H:%M:%S}[/] "
|
|
319
|
-
return ""
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
# %% Test function run
|
|
324
|
-
if __name__ == "__main__":
|
|
325
|
-
from corelp import test
|
|
326
|
-
test(__file__)
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# Date : 2025-08-27
|
|
4
|
-
# Author : Lancelot PINCET
|
|
5
|
-
# GitHub : https://github.com/LancelotPincet
|
|
6
|
-
# Library : coreLP
|
|
7
|
-
# Module : print
|
|
8
|
-
|
|
9
|
-
"""
|
|
10
|
-
This file allows to test print
|
|
11
|
-
|
|
12
|
-
print : This function overrides python built in print function to add functionnalities.
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# %% Libraries
|
|
18
|
-
from corelp import print, debug
|
|
19
|
-
import pytest
|
|
20
|
-
from time import sleep
|
|
21
|
-
debug_folder = debug(__file__)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# %% test prints
|
|
25
|
-
def test_print() :
|
|
26
|
-
'''
|
|
27
|
-
Test print
|
|
28
|
-
'''
|
|
29
|
-
string = "# TEST\nHello *world*!\n\nThis is 1 print **example**"
|
|
30
|
-
print(string, style="magenta")
|
|
31
|
-
print.print(string, style="magenta")
|
|
32
|
-
print.log(string, style="magenta")
|
|
33
|
-
print.pyprint(string)
|
|
34
|
-
print.richprint(string)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
# %% test verbose
|
|
39
|
-
def test_verbose() :
|
|
40
|
-
'''
|
|
41
|
-
Test verbose
|
|
42
|
-
'''
|
|
43
|
-
print.verbose = False # Muting
|
|
44
|
-
print("Should not print") # Does not print
|
|
45
|
-
print("Should print", verbose=True) # Does print
|
|
46
|
-
print("Should not print") # Does not print
|
|
47
|
-
print.verbose = True # Unmuting
|
|
48
|
-
print("Should print") # Does print
|
|
49
|
-
print("Should not print", verbose=False) # Does not print
|
|
50
|
-
print("Should print") # Does print
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
# %% test logging
|
|
55
|
-
def test_logging() :
|
|
56
|
-
'''
|
|
57
|
-
Test logging
|
|
58
|
-
'''
|
|
59
|
-
print.theme = {"success" : "green"}
|
|
60
|
-
string = "# TEST\nHello *world*!\n\nThis is 1 print **example**"
|
|
61
|
-
print(string, style="success")
|
|
62
|
-
print.print_locals()
|
|
63
|
-
try :
|
|
64
|
-
1/0
|
|
65
|
-
except Exception :
|
|
66
|
-
print.error()
|
|
67
|
-
file = debug_folder / "log.html"
|
|
68
|
-
print.export_html(file)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
# %% test console
|
|
73
|
-
def test_console() :
|
|
74
|
-
'''
|
|
75
|
-
Test console
|
|
76
|
-
'''
|
|
77
|
-
file = debug_folder / 'log.md'
|
|
78
|
-
print.file = file
|
|
79
|
-
string = "# TEST\nHello *world*!\n\nThis is 1 print **example**"
|
|
80
|
-
print(string, style="magenta")
|
|
81
|
-
assert file.exists()
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
# %% test clock
|
|
86
|
-
def test_clock() :
|
|
87
|
-
'''
|
|
88
|
-
Test clock
|
|
89
|
-
'''
|
|
90
|
-
for i in print.clock(5, "Outer loop") :
|
|
91
|
-
print("Should not print")
|
|
92
|
-
for j in print.clock(5, "Inner loop") :
|
|
93
|
-
sleep(1)
|
|
94
|
-
print("Should not print")
|
|
95
|
-
|
|
96
|
-
for i in print.clock(10, "Other loop") :
|
|
97
|
-
sleep(1)
|
|
98
|
-
print("Should not print")
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
# %% Test function run
|
|
106
|
-
if __name__ == "__main__":
|
|
107
|
-
from corelp import test
|
|
108
|
-
test(__file__)
|
|
File without changes
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# Date : 2025-11-30
|
|
4
|
-
# Author : Lancelot PINCET
|
|
5
|
-
# GitHub : https://github.com/LancelotPincet
|
|
6
|
-
# Library : coreLP
|
|
7
|
-
# Module : user_inputs
|
|
8
|
-
|
|
9
|
-
"""
|
|
10
|
-
This file allows to test user_inputs
|
|
11
|
-
|
|
12
|
-
user_inputs : Gets last user inputs dictionnary from global variables.
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# %% Libraries
|
|
18
|
-
from corelp import print, debug
|
|
19
|
-
import pytest
|
|
20
|
-
from corelp import user_inputs
|
|
21
|
-
debug_folder = debug(__file__)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
# %% Function test
|
|
26
|
-
def test_user_inputs() :
|
|
27
|
-
'''
|
|
28
|
-
Test user_inputs function
|
|
29
|
-
'''
|
|
30
|
-
user_inputs() #init
|
|
31
|
-
a = 1
|
|
32
|
-
inputs = user_inputs()
|
|
33
|
-
if inputs != {'a': 1} :
|
|
34
|
-
raise ValueError(f'{inputs} should be dict(a=1)')
|
|
35
|
-
user_inputs() #init
|
|
36
|
-
b = 2
|
|
37
|
-
inputs = user_inputs()
|
|
38
|
-
if inputs != {'b': 2} :
|
|
39
|
-
raise ValueError(f'{inputs} should be dict(b=2)')
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
# %% Test function run
|
|
44
|
-
if __name__ == "__main__":
|
|
45
|
-
from corelp import test
|
|
46
|
-
test(__file__)
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# Date : 2025-11-30
|
|
4
|
-
# Author : Lancelot PINCET
|
|
5
|
-
# GitHub : https://github.com/LancelotPincet
|
|
6
|
-
# Library : coreLP
|
|
7
|
-
# Module : user_inputs
|
|
8
|
-
|
|
9
|
-
"""
|
|
10
|
-
Gets last user inputs dictionnary from global variables.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
# %% Libraries
|
|
16
|
-
import inspect
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
# %% Function
|
|
21
|
-
|
|
22
|
-
def user_inputs(reset=False) :
|
|
23
|
-
r"""
|
|
24
|
-
Return a dictionary of variables defined by the user in the interactive environment.
|
|
25
|
-
|
|
26
|
-
Parameters
|
|
27
|
-
----------
|
|
28
|
-
reset : bool or str
|
|
29
|
-
True to set as first call, String value to define a group of parameters
|
|
30
|
-
|
|
31
|
-
Returns
|
|
32
|
-
-------
|
|
33
|
-
dict
|
|
34
|
-
A dictionary containing the user's currently defined variables.
|
|
35
|
-
|
|
36
|
-
Examples
|
|
37
|
-
--------
|
|
38
|
-
>>> from corelp import user_inputs
|
|
39
|
-
>>> user_inputs(True) # First call (initializes and clears import-related variables)
|
|
40
|
-
None
|
|
41
|
-
>>> a = 1 # User defines a variable
|
|
42
|
-
>>> user_inputs() # Now returns: {'a': 1}
|
|
43
|
-
{'a': 1}
|
|
44
|
-
"""
|
|
45
|
-
frame = inspect.currentframe().f_back
|
|
46
|
-
ns = {**frame.f_globals, **frame.f_locals}
|
|
47
|
-
|
|
48
|
-
# ---- Filter user variables (ignore internals starting with "_") ----
|
|
49
|
-
ns = {key: value for key, value in ns.items() if not key.startswith("_")}
|
|
50
|
-
|
|
51
|
-
# Validate status
|
|
52
|
-
if reset :
|
|
53
|
-
user_inputs.current_group = reset if isinstance(reset, str) else None
|
|
54
|
-
user_inputs.cache = None
|
|
55
|
-
|
|
56
|
-
# Case when user_inputs is on top : cache = None
|
|
57
|
-
if user_inputs.cache is None :
|
|
58
|
-
user_inputs.cache = ns
|
|
59
|
-
return
|
|
60
|
-
|
|
61
|
-
# Case when user_inputs is at bottom : cache = dict
|
|
62
|
-
else :
|
|
63
|
-
updated = { key: value for key, value in ns.items() if key not in user_inputs.cache or user_inputs.cache[key] is not value}
|
|
64
|
-
values = {key: value for key, value in updated.items() if not key.endswith('_')}
|
|
65
|
-
comments = {key: value for key, value in updated.items() if key.endswith('_')}
|
|
66
|
-
|
|
67
|
-
# Group values
|
|
68
|
-
if user_inputs.current_group is not None :
|
|
69
|
-
user_inputs.groups_values[user_inputs.current_group] = values
|
|
70
|
-
user_inputs.groups_comments[user_inputs.current_group] = comments
|
|
71
|
-
|
|
72
|
-
# End
|
|
73
|
-
user_inputs.current_group = None
|
|
74
|
-
user_inputs.cache = None
|
|
75
|
-
return values
|
|
76
|
-
|
|
77
|
-
user_inputs.cache = None
|
|
78
|
-
user_inputs.current_group = None
|
|
79
|
-
user_inputs.groups_values = {}
|
|
80
|
-
user_inputs.groups_comments = {}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
# %% Test function run
|
|
85
|
-
if __name__ == "__main__":
|
|
86
|
-
from corelp import test
|
|
87
|
-
test(__file__)
|