rootlp 0.1.7__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.
- rootlp/__init__.py +23 -0
- rootlp/modules/Section_LP/Section.py +177 -0
- rootlp/modules/Section_LP/__init__.py +0 -0
- rootlp/modules/Section_LP/test_Section.py +44 -0
- rootlp/modules/__init__.py +0 -0
- rootlp/modules/getfunction_LP/__init__.py +0 -0
- rootlp/modules/getfunction_LP/getfunction.py +97 -0
- rootlp/modules/getfunction_LP/test_getfunction.py +79 -0
- rootlp/modules/main_LP/__init__.py +0 -0
- rootlp/modules/main_LP/main.py +437 -0
- rootlp/modules/main_LP/test_main.py +74 -0
- rootlp/modules/menu_LP/__init__.py +0 -0
- rootlp/modules/menu_LP/menu.py +78 -0
- rootlp/modules/menu_LP/test_menu.py +79 -0
- rootlp/modules/mo_LP/__init__.py +0 -0
- rootlp/modules/mo_LP/mo.py +23 -0
- rootlp/modules/mo_LP/test_mo.py +79 -0
- rootlp/modules/print_LP/__init__.py +0 -0
- rootlp/modules/print_LP/print.py +337 -0
- rootlp/modules/print_LP/test_print.py +109 -0
- rootlp/modules/project_server_LP/__init__.py +0 -0
- rootlp/modules/project_server_LP/project_server.py +86 -0
- rootlp/modules/project_server_LP/test_project_server.py +79 -0
- rootlp/modules/readme_string_LP/__init__.py +0 -0
- rootlp/modules/readme_string_LP/readme_string.py +53 -0
- rootlp/modules/readme_string_LP/test_readme_string.py +79 -0
- rootlp/modules/user_inputs_LP/__init__.py +0 -0
- rootlp/modules/user_inputs_LP/test_user_inputs.py +46 -0
- rootlp/modules/user_inputs_LP/user_inputs.py +103 -0
- rootlp/modules.json +56 -0
- rootlp/py.typed +0 -0
- rootlp/scripts/__init__.py +0 -0
- rootlp/scripts.json +1 -0
- rootlp-0.1.7.dist-info/METADATA +41 -0
- rootlp-0.1.7.dist-info/RECORD +36 -0
- rootlp-0.1.7.dist-info/WHEEL +4 -0
rootlp/__init__.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2026-01-10
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : rootLP
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
A library that gathers root functions for custom script execution.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# %% Lazy imports
|
|
15
|
+
from corelp import getmodule
|
|
16
|
+
__getattr__, __all__ = getmodule(__file__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# %% Test function run
|
|
21
|
+
if __name__ == "__main__":
|
|
22
|
+
from corelp import test
|
|
23
|
+
test(__file__)
|
|
@@ -0,0 +1,177 @@
|
|
|
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 : rootLP
|
|
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 folder, selfkwargs, kwargsself
|
|
17
|
+
from rootlp import print
|
|
18
|
+
from dataclasses import dataclass
|
|
19
|
+
import pickle
|
|
20
|
+
import joblib
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from functools import wraps
|
|
23
|
+
import hashlib
|
|
24
|
+
import inspect
|
|
25
|
+
import os
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# %% Class
|
|
30
|
+
@dataclass(slots=True, kw_only=True)
|
|
31
|
+
class Section() :
|
|
32
|
+
'''
|
|
33
|
+
This class defines decorator instances allowing to create section functions.
|
|
34
|
+
Cache results into a folder, if another call occurs, can load-back the precalculated data.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
path : str or Path
|
|
39
|
+
path where to save section folder results.
|
|
40
|
+
new : bool
|
|
41
|
+
True to ignore pre-calculated data and crush them.
|
|
42
|
+
num : int
|
|
43
|
+
Index of section, after one call, adds 1 for next call.
|
|
44
|
+
parent_path : str or Path
|
|
45
|
+
Path to the parent folder if bulk processing.
|
|
46
|
+
|
|
47
|
+
Examples
|
|
48
|
+
--------
|
|
49
|
+
>>> from corelp import Section
|
|
50
|
+
...
|
|
51
|
+
>>> section = Section(path=export_path)
|
|
52
|
+
...
|
|
53
|
+
>>> @section()
|
|
54
|
+
... def add(a, b=0) :
|
|
55
|
+
... testfunc.print('Hello World')
|
|
56
|
+
... return a + b
|
|
57
|
+
...
|
|
58
|
+
>>> testfunc.print('3+0=', add(3)) # First call calculates and save result
|
|
59
|
+
>>> testfunc.print('3+0=', add(3, 0)) # Second call loads back precalculated results
|
|
60
|
+
>>> testfunc.print('1+3=', add(1, 3)) # New call with other parameters : crushed previous results with new ones
|
|
61
|
+
>>> testfunc.print('1+3=', add(1, b=3)) # Second call with these parameters : loads precalculated results
|
|
62
|
+
...
|
|
63
|
+
>>> @section(cache=False) # Creates an index of 2, does no caching
|
|
64
|
+
... def sub(a, b=0) :
|
|
65
|
+
... return a - b
|
|
66
|
+
...
|
|
67
|
+
>>> @section(num=10) # Creates an index of 10
|
|
68
|
+
... def mul(a, b=0) :
|
|
69
|
+
... return a * b
|
|
70
|
+
...
|
|
71
|
+
>>> @section(new=True) # Creates an index of 11, always creates new cache
|
|
72
|
+
... def div(a, b) :
|
|
73
|
+
... return a / b
|
|
74
|
+
'''
|
|
75
|
+
|
|
76
|
+
# Attributes
|
|
77
|
+
path : Path | str = None
|
|
78
|
+
new :bool = False
|
|
79
|
+
num :int = 0
|
|
80
|
+
parent_path : Path | str = None
|
|
81
|
+
|
|
82
|
+
# Init
|
|
83
|
+
def __post_init__(self) :
|
|
84
|
+
if self.path is not None :
|
|
85
|
+
self.path = Path(self.path)
|
|
86
|
+
if self.parent_path is not None :
|
|
87
|
+
self.parent_path = Path(self.parent_path)
|
|
88
|
+
|
|
89
|
+
# Decorator
|
|
90
|
+
def __call__(self, *, new=None, num=None, symlink=None, cache=True):
|
|
91
|
+
if new is None :
|
|
92
|
+
new = self.new
|
|
93
|
+
if num is None :
|
|
94
|
+
num = self.num
|
|
95
|
+
self.num = num+1
|
|
96
|
+
|
|
97
|
+
def decorator(func) :
|
|
98
|
+
name = func.__name__
|
|
99
|
+
|
|
100
|
+
@wraps(func)
|
|
101
|
+
def wrapper(*args, **kwargs):
|
|
102
|
+
wrapper.path = self.path / f"{num:03}_{name}"
|
|
103
|
+
print(f'\n#### **{num}. {name.replace("_"," ")} section**\n')
|
|
104
|
+
|
|
105
|
+
# Creating hash
|
|
106
|
+
if cache :
|
|
107
|
+
print('**Call hash:**', do_stdout=False)
|
|
108
|
+
bound = inspect.signature(func).bind(*args, **kwargs)
|
|
109
|
+
bound.apply_defaults()
|
|
110
|
+
serialized = pickle.dumps(bound.arguments)
|
|
111
|
+
args_hash = hashlib.md5(serialized).hexdigest()
|
|
112
|
+
result_file = wrapper.path / f'{args_hash}.pkl'
|
|
113
|
+
print(f'*{args_hash}*\n', do_stdout=False)
|
|
114
|
+
|
|
115
|
+
# Checking already calculated exists
|
|
116
|
+
if result_file.exists() and not new :
|
|
117
|
+
print('**Loading from *precalculated* results...**')
|
|
118
|
+
with open(result_file, 'rb') as f:
|
|
119
|
+
result = joblib.load(f)
|
|
120
|
+
print('...loaded\n')
|
|
121
|
+
return result
|
|
122
|
+
|
|
123
|
+
# Calculations
|
|
124
|
+
folder(wrapper.path, warning=False)
|
|
125
|
+
print('**Calculating results:**')
|
|
126
|
+
print_status = kwargsself(print)
|
|
127
|
+
print.file = wrapper.path / f'{name}_log.md'
|
|
128
|
+
result = func(*args, **kwargs)
|
|
129
|
+
selfkwargs(print, print_status)
|
|
130
|
+
print('...calculated\n')
|
|
131
|
+
|
|
132
|
+
# Caching
|
|
133
|
+
if cache :
|
|
134
|
+
print('**Saving results:**')
|
|
135
|
+
with open(result_file, 'wb') as f:
|
|
136
|
+
joblib.dump(result, f)
|
|
137
|
+
print('...saved\n')
|
|
138
|
+
|
|
139
|
+
# Create symlink
|
|
140
|
+
if symlink is not None :
|
|
141
|
+
print('**Creating symlinks:**')
|
|
142
|
+
for link in symlink :
|
|
143
|
+
print(f"- {link}")
|
|
144
|
+
link_path = Path(link)
|
|
145
|
+
link_folder = self.parent_path.parent / f'_outputs/{link_path.stem}'
|
|
146
|
+
new_stem = str(self.subfolder.as_posix()).replace('/', '--').replace(' ', '_')
|
|
147
|
+
if not link_folder.exists() :
|
|
148
|
+
folder(link_folder, warning=False)
|
|
149
|
+
link_from = wrapper.path / link_path
|
|
150
|
+
link_to = link_folder / f"{new_stem}{link_path.suffix}"
|
|
151
|
+
if link_to.exists() or link_to.is_symlink():
|
|
152
|
+
link_to.unlink()
|
|
153
|
+
if os.name == "nt":
|
|
154
|
+
try :
|
|
155
|
+
link_to.symlink_to(link_from, link_from.is_dir())
|
|
156
|
+
except OSError :
|
|
157
|
+
print("Windows does not allow to create symlink, aborting. Consider using Windows in Developper mode.")
|
|
158
|
+
break
|
|
159
|
+
else:
|
|
160
|
+
link_to.symlink_to(link_from)
|
|
161
|
+
print('...created\n')
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
return result
|
|
165
|
+
return wrapper
|
|
166
|
+
return decorator
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def subfolder(self) :
|
|
170
|
+
return self.path.relative_to(self.parent_path)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
# %% Test function run
|
|
175
|
+
if __name__ == "__main__":
|
|
176
|
+
from corelp import test
|
|
177
|
+
test(__file__)
|
|
File without changes
|
|
@@ -0,0 +1,44 @@
|
|
|
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 : rootLP
|
|
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
|
|
19
|
+
from rootlp import Section
|
|
20
|
+
debug_folder = debug(__file__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# %% Function test
|
|
25
|
+
def test_function() :
|
|
26
|
+
'''
|
|
27
|
+
Test Section function
|
|
28
|
+
'''
|
|
29
|
+
section = Section(path=debug_folder)
|
|
30
|
+
|
|
31
|
+
@section()
|
|
32
|
+
def add(a, b=0) :
|
|
33
|
+
return a+b
|
|
34
|
+
assert add(3) == 3
|
|
35
|
+
assert add(3, 0) == 3
|
|
36
|
+
assert add(1, 3) == 4
|
|
37
|
+
assert add(1, b=3) == 4
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# %% Test function run
|
|
42
|
+
if __name__ == "__main__":
|
|
43
|
+
from corelp import test
|
|
44
|
+
test(__file__)
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2026-01-11
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : rootLP
|
|
7
|
+
# Module : getmodule
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This function is to be used in a script source __init__ file It creates lazy imports of the module imported and defines __getattr__ and __all__ for this source.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# %% Libraries
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
import importlib
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# %% Function
|
|
22
|
+
def getfunction(file) :
|
|
23
|
+
'''
|
|
24
|
+
This function is to be used in a script source __init__ file It creates lazy imports of the module imported and defines __getattr__ and __all__ for this source.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
file : str
|
|
29
|
+
__file__ string in the __init__.py file.
|
|
30
|
+
|
|
31
|
+
Returns
|
|
32
|
+
-------
|
|
33
|
+
_getattr : function
|
|
34
|
+
Function to replace __getattr__ variable.
|
|
35
|
+
_all : list
|
|
36
|
+
list of module names corresponding to __all__.
|
|
37
|
+
|
|
38
|
+
Raises
|
|
39
|
+
------
|
|
40
|
+
AttributeError
|
|
41
|
+
When trying to import a module which is not in the library.
|
|
42
|
+
|
|
43
|
+
Examples
|
|
44
|
+
--------
|
|
45
|
+
>>> from rootlp import getmodule
|
|
46
|
+
...
|
|
47
|
+
>>> # In __init__.py file
|
|
48
|
+
... __getattr__, __all__ = getmodule(__file__)
|
|
49
|
+
'''
|
|
50
|
+
|
|
51
|
+
# Get paths
|
|
52
|
+
file = Path(file)
|
|
53
|
+
srcfolder = file.parent
|
|
54
|
+
name = srcfolder.name
|
|
55
|
+
|
|
56
|
+
# Function folders
|
|
57
|
+
modules = {}
|
|
58
|
+
for folder in srcfolder.iterdir() :
|
|
59
|
+
if not folder.name.endswith('_functions') :
|
|
60
|
+
continue
|
|
61
|
+
for file in folder.iterdir() :
|
|
62
|
+
if file.stem.startswith('__') or file.suffix != '.py':
|
|
63
|
+
continue
|
|
64
|
+
stem = file.stem
|
|
65
|
+
modules[stem] = folder
|
|
66
|
+
|
|
67
|
+
# Objects to return
|
|
68
|
+
_lazy = {}
|
|
69
|
+
_all = [module for module in modules]
|
|
70
|
+
def _getattr(attr) :
|
|
71
|
+
|
|
72
|
+
# Cached
|
|
73
|
+
if attr in _lazy:
|
|
74
|
+
return _lazy[attr]
|
|
75
|
+
|
|
76
|
+
try :
|
|
77
|
+
folder = modules.get(attr, None)
|
|
78
|
+
if folder is None :
|
|
79
|
+
raise KeyError(f"{attr} was not found in modules")
|
|
80
|
+
except KeyError:
|
|
81
|
+
raise AttributeError(f'module {name} has no attribute {attr}')
|
|
82
|
+
|
|
83
|
+
mod = importlib.import_module(f"{name}.{folder.name}.{attr}")
|
|
84
|
+
obj = getattr(mod, attr, None)
|
|
85
|
+
if obj is None :
|
|
86
|
+
raise AttributeError(f"module {name}.{folder.name}.{attr} has no attribute {attr}")
|
|
87
|
+
_lazy[attr] = obj # Cache it
|
|
88
|
+
return obj
|
|
89
|
+
|
|
90
|
+
return _getattr, _all
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# %% Test function run
|
|
95
|
+
if __name__ == "__main__":
|
|
96
|
+
from corelp import test
|
|
97
|
+
test(__file__)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2026-01-11
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : rootLP
|
|
7
|
+
# Module : getmodule
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This file allows to test getmodule
|
|
11
|
+
|
|
12
|
+
getmodule : This function is to be used in a script source __init__ file It creates lazy imports of the module imported and defines __getattr__ and __all__ for this source.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# %% Libraries
|
|
18
|
+
from corelp import print, debug
|
|
19
|
+
import pytest
|
|
20
|
+
from rootlp import getmodule
|
|
21
|
+
debug_folder = debug(__file__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# %% Function test
|
|
26
|
+
def test_function() :
|
|
27
|
+
'''
|
|
28
|
+
Test getmodule function
|
|
29
|
+
'''
|
|
30
|
+
print('Hello world!')
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# %% Instance fixture
|
|
35
|
+
@pytest.fixture()
|
|
36
|
+
def instance() :
|
|
37
|
+
'''
|
|
38
|
+
Create a new instance at each test function
|
|
39
|
+
'''
|
|
40
|
+
return getmodule()
|
|
41
|
+
|
|
42
|
+
def test_instance(instance) :
|
|
43
|
+
'''
|
|
44
|
+
Test on fixture
|
|
45
|
+
'''
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# %% Returns test
|
|
50
|
+
@pytest.mark.parametrize("args, kwargs, expected, message", [
|
|
51
|
+
#([], {}, None, ""),
|
|
52
|
+
([], {}, None, ""),
|
|
53
|
+
])
|
|
54
|
+
def test_returns(args, kwargs, expected, message) :
|
|
55
|
+
'''
|
|
56
|
+
Test getmodule return values
|
|
57
|
+
'''
|
|
58
|
+
assert getmodule(*args, **kwargs) == expected, message
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# %% Error test
|
|
63
|
+
@pytest.mark.parametrize("args, kwargs, error, error_message", [
|
|
64
|
+
#([], {}, None, ""),
|
|
65
|
+
([], {}, None, ""),
|
|
66
|
+
])
|
|
67
|
+
def test_errors(args, kwargs, error, error_message) :
|
|
68
|
+
'''
|
|
69
|
+
Test getmodule error values
|
|
70
|
+
'''
|
|
71
|
+
with pytest.raises(error, match=error_message) :
|
|
72
|
+
getmodule(*args, **kwargs)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# %% Test function run
|
|
77
|
+
if __name__ == "__main__":
|
|
78
|
+
from corelp import test
|
|
79
|
+
test(__file__)
|
|
File without changes
|