corelp 1.0.36__tar.gz → 1.0.38__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.
- {corelp-1.0.36 → corelp-1.0.38}/PKG-INFO +1 -6
- {corelp-1.0.36 → corelp-1.0.38}/pyproject.toml +5 -7
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/Path_LP/test_Path.py +1 -1
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/rfrom_LP/test_rfrom.py +1 -1
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules.json +0 -24
- corelp-1.0.36/src/corelp/modules/Section_LP/Section.py +0 -176
- corelp-1.0.36/src/corelp/modules/Section_LP/test_Section.py +0 -43
- corelp-1.0.36/src/corelp/modules/main_LP/main.py +0 -251
- corelp-1.0.36/src/corelp/modules/main_LP/test_main.py +0 -74
- corelp-1.0.36/src/corelp/modules/print_LP/print.py +0 -326
- corelp-1.0.36/src/corelp/modules/print_LP/test_print.py +0 -108
- corelp-1.0.36/src/corelp/modules/selfkwargs_LP/__init__.py +0 -0
- corelp-1.0.36/src/corelp/modules/test_LP/__init__.py +0 -0
- corelp-1.0.36/src/corelp/modules/user_inputs_LP/__init__.py +0 -0
- corelp-1.0.36/src/corelp/modules/user_inputs_LP/test_user_inputs.py +0 -46
- corelp-1.0.36/src/corelp/modules/user_inputs_LP/user_inputs.py +0 -87
- corelp-1.0.36/src/corelp/scripts/__init__.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/README.md +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/__init__.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/icon_pythonLP.png +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/Path_LP/Path.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/Path_LP/__init__.py +0 -0
- {corelp-1.0.36/src/corelp/modules/Section_LP → corelp-1.0.38/src/corelp/modules}/__init__.py +0 -0
- {corelp-1.0.36/src/corelp/modules → corelp-1.0.38/src/corelp/modules/debug_LP}/__init__.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/debug_LP/debug.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/debug_LP/test_debug.py +0 -0
- {corelp-1.0.36/src/corelp/modules/debug_LP → corelp-1.0.38/src/corelp/modules/folder_LP}/__init__.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/folder_LP/folder.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/folder_LP/test_folder.py +0 -0
- {corelp-1.0.36/src/corelp/modules/folder_LP → corelp-1.0.38/src/corelp/modules/getmodule_LP}/__init__.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/getmodule_LP/getmodule.py +0 -0
- {corelp-1.0.36/src/corelp/modules/getmodule_LP → corelp-1.0.38/src/corelp/modules/kwargsself_LP}/__init__.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/kwargsself_LP/kwargsself.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/kwargsself_LP/test_kwargsself.py +0 -0
- {corelp-1.0.36/src/corelp/modules/kwargsself_LP → corelp-1.0.38/src/corelp/modules/prop_LP}/__init__.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/prop_LP/prop.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/prop_LP/test_prop.py +0 -0
- {corelp-1.0.36/src/corelp/modules/main_LP → corelp-1.0.38/src/corelp/modules/rfrom_LP}/__init__.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/rfrom_LP/rfrom.py +0 -0
- {corelp-1.0.36/src/corelp/modules/print_LP → corelp-1.0.38/src/corelp/modules/selfkwargs_LP}/__init__.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/selfkwargs_LP/selfkwargs.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/selfkwargs_LP/test_selfkwargs.py +0 -0
- {corelp-1.0.36/src/corelp/modules/prop_LP → corelp-1.0.38/src/corelp/modules/test_LP}/__init__.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/test_LP/test.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/modules/test_LP/test_test.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/py.typed +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/pythonLP.png:Zone.Identifier +0 -0
- {corelp-1.0.36/src/corelp/modules/rfrom_LP → corelp-1.0.38/src/corelp/scripts}/__init__.py +0 -0
- {corelp-1.0.36 → corelp-1.0.38}/src/corelp/scripts.json +0 -0
|
@@ -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
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "corelp"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.38"
|
|
4
4
|
description = "A library that gathers core functions for python programming."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
7
7
|
dependencies = []
|
|
8
8
|
|
|
9
9
|
[build-system]
|
|
10
|
-
requires = [ "uv_build
|
|
10
|
+
requires = [ "uv_build",]
|
|
11
11
|
build-backend = "uv_build"
|
|
12
12
|
|
|
13
13
|
[dependency-groups]
|
|
14
|
-
|
|
14
|
+
tests = [ "pytest",]
|
|
15
15
|
docs = [ "sphinx", "sphinx-design", "sphinx-rtd-theme", "toml",]
|
|
16
16
|
anaconda = [ "ipykernel", "spyder-kernels",]
|
|
17
17
|
|
|
18
|
-
[project.optional-dependencies]
|
|
19
|
-
lib = []
|
|
20
|
-
script = [ "joblib", "rich", "marimo",]
|
|
21
|
-
|
|
22
18
|
[tool.uv]
|
|
23
19
|
required-environments = [ "sys_platform == 'linux' and platform_machine == 'x86_64'", "sys_platform == 'win32' and (platform_machine == 'AMD64' or platform_machine == 'x86_64')",]
|
|
20
|
+
|
|
21
|
+
[tool.uv.sources]
|
|
@@ -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,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__)
|
|
@@ -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__)
|
|
@@ -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__)
|