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.
Files changed (36) hide show
  1. rootlp/__init__.py +23 -0
  2. rootlp/modules/Section_LP/Section.py +177 -0
  3. rootlp/modules/Section_LP/__init__.py +0 -0
  4. rootlp/modules/Section_LP/test_Section.py +44 -0
  5. rootlp/modules/__init__.py +0 -0
  6. rootlp/modules/getfunction_LP/__init__.py +0 -0
  7. rootlp/modules/getfunction_LP/getfunction.py +97 -0
  8. rootlp/modules/getfunction_LP/test_getfunction.py +79 -0
  9. rootlp/modules/main_LP/__init__.py +0 -0
  10. rootlp/modules/main_LP/main.py +437 -0
  11. rootlp/modules/main_LP/test_main.py +74 -0
  12. rootlp/modules/menu_LP/__init__.py +0 -0
  13. rootlp/modules/menu_LP/menu.py +78 -0
  14. rootlp/modules/menu_LP/test_menu.py +79 -0
  15. rootlp/modules/mo_LP/__init__.py +0 -0
  16. rootlp/modules/mo_LP/mo.py +23 -0
  17. rootlp/modules/mo_LP/test_mo.py +79 -0
  18. rootlp/modules/print_LP/__init__.py +0 -0
  19. rootlp/modules/print_LP/print.py +337 -0
  20. rootlp/modules/print_LP/test_print.py +109 -0
  21. rootlp/modules/project_server_LP/__init__.py +0 -0
  22. rootlp/modules/project_server_LP/project_server.py +86 -0
  23. rootlp/modules/project_server_LP/test_project_server.py +79 -0
  24. rootlp/modules/readme_string_LP/__init__.py +0 -0
  25. rootlp/modules/readme_string_LP/readme_string.py +53 -0
  26. rootlp/modules/readme_string_LP/test_readme_string.py +79 -0
  27. rootlp/modules/user_inputs_LP/__init__.py +0 -0
  28. rootlp/modules/user_inputs_LP/test_user_inputs.py +46 -0
  29. rootlp/modules/user_inputs_LP/user_inputs.py +103 -0
  30. rootlp/modules.json +56 -0
  31. rootlp/py.typed +0 -0
  32. rootlp/scripts/__init__.py +0 -0
  33. rootlp/scripts.json +1 -0
  34. rootlp-0.1.7.dist-info/METADATA +41 -0
  35. rootlp-0.1.7.dist-info/RECORD +36 -0
  36. 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