corelp 1.0.28__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 (48) hide show
  1. corelp/__init__.py +29 -0
  2. corelp/icon_pythonLP.ico +0 -0
  3. corelp/modules/Path_LP/Path.py +92 -0
  4. corelp/modules/Path_LP/__init__.py +0 -0
  5. corelp/modules/Path_LP/test_Path.py +37 -0
  6. corelp/modules/Section_LP/Section.py +176 -0
  7. corelp/modules/Section_LP/__init__.py +0 -0
  8. corelp/modules/Section_LP/test_Section.py +43 -0
  9. corelp/modules/__init__.py +0 -0
  10. corelp/modules/debug_LP/__init__.py +0 -0
  11. corelp/modules/debug_LP/debug.py +66 -0
  12. corelp/modules/debug_LP/test_debug.py +34 -0
  13. corelp/modules/folder_LP/__init__.py +0 -0
  14. corelp/modules/folder_LP/folder.py +96 -0
  15. corelp/modules/folder_LP/test_folder.py +43 -0
  16. corelp/modules/getmodule_LP/__init__.py +0 -0
  17. corelp/modules/getmodule_LP/getmodule.py +101 -0
  18. corelp/modules/kwargsself_LP/__init__.py +0 -0
  19. corelp/modules/kwargsself_LP/kwargsself.py +80 -0
  20. corelp/modules/kwargsself_LP/test_kwargsself.py +59 -0
  21. corelp/modules/main_LP/__init__.py +0 -0
  22. corelp/modules/main_LP/main.py +237 -0
  23. corelp/modules/main_LP/test_main.py +74 -0
  24. corelp/modules/print_LP/__init__.py +0 -0
  25. corelp/modules/print_LP/print.py +317 -0
  26. corelp/modules/print_LP/test_print.py +108 -0
  27. corelp/modules/prop_LP/__init__.py +0 -0
  28. corelp/modules/prop_LP/prop.py +134 -0
  29. corelp/modules/prop_LP/test_prop.py +104 -0
  30. corelp/modules/rfrom_LP/__init__.py +0 -0
  31. corelp/modules/rfrom_LP/rfrom.py +72 -0
  32. corelp/modules/rfrom_LP/test_rfrom.py +37 -0
  33. corelp/modules/selfkwargs_LP/__init__.py +0 -0
  34. corelp/modules/selfkwargs_LP/selfkwargs.py +51 -0
  35. corelp/modules/selfkwargs_LP/test_selfkwargs.py +41 -0
  36. corelp/modules/test_LP/__init__.py +0 -0
  37. corelp/modules/test_LP/test.py +61 -0
  38. corelp/modules/test_LP/test_test.py +33 -0
  39. corelp/modules/user_inputs_LP/__init__.py +0 -0
  40. corelp/modules/user_inputs_LP/test_user_inputs.py +45 -0
  41. corelp/modules/user_inputs_LP/user_inputs.py +81 -0
  42. corelp/modules.json +80 -0
  43. corelp/py.typed +0 -0
  44. corelp/scripts/__init__.py +0 -0
  45. corelp/scripts.json +1 -0
  46. corelp-1.0.28.dist-info/METADATA +41 -0
  47. corelp-1.0.28.dist-info/RECORD +48 -0
  48. corelp-1.0.28.dist-info/WHEEL +4 -0
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # Date : 2025-08-25
4
+ # Author : Lancelot PINCET
5
+ # GitHub : https://github.com/LancelotPincet
6
+ # Library : coreLP
7
+ # Module : getmodule
8
+
9
+ """
10
+ This function is to be used in a library __init__ file. It creates lazy imports of the module imported and defines __getattr__ and __all__ for this library.
11
+ """
12
+
13
+
14
+
15
+ # %% Libraries
16
+ from pathlib import Path
17
+ import json
18
+ import importlib
19
+
20
+
21
+
22
+ # %% Function
23
+ def getmodule(file) :
24
+ '''
25
+ This function is to be used in a library __init__ file. It creates lazy imports of the module imported and defines __getattr__ and __all__ for this library.
26
+
27
+ Parameters
28
+ ----------
29
+ file : str
30
+ __file__ string in the __init__.py file.
31
+
32
+ Returns
33
+ -------
34
+ _getattr : function
35
+ Function to replace __getattr__ variable.
36
+ _all : list
37
+ list of module names corresponding to __all__.
38
+
39
+ Raises
40
+ ------
41
+ AttributeError
42
+ When trying to import a module which is not in the library.
43
+
44
+ Examples
45
+ --------
46
+ >>> from corelp import getmodule
47
+ ...
48
+ >>> # In __init__.py file
49
+ ... __getattr__, __all__ = getmodule(__file__)
50
+ '''
51
+
52
+ # Get paths
53
+ file = Path(file)
54
+ libfolder = file.parent
55
+ name = libfolder.name
56
+ modulesjson = libfolder / 'modules.json'
57
+ scriptsjson = libfolder / 'scripts.json'
58
+
59
+ # Get dicts
60
+ with open(modulesjson, "r") as file :
61
+ modules = json.load(file)
62
+ with open(scriptsjson, "r") as file :
63
+ scripts = json.load(file)
64
+
65
+ # Objects to return
66
+ _lazy = {}
67
+ _all = [module for module in modules] + [script for script in scripts]
68
+ def _getattr(attr) :
69
+
70
+ # Cached
71
+ if attr in _lazy:
72
+ return _lazy[attr]
73
+
74
+ try :
75
+ module = modules.get(attr, None)
76
+ funcstring = "module"
77
+ if module is None :
78
+ module = scripts.get(attr, None)
79
+ funcstring = "script"
80
+ if module is None :
81
+ raise KeyError(f"{attr} was not found in json files")
82
+ except KeyError:
83
+ raise AttributeError(f'module {name} has no attribute {attr}')
84
+ path2module = module[funcstring].replace('/', '.')
85
+ obj_name = module["object"]
86
+
87
+ mod = importlib.import_module(f"{name}.{path2module}")
88
+ obj = getattr(mod, obj_name, None)
89
+ if obj is None :
90
+ raise AttributeError(f"module {name}.{path2module} has no attribute {obj_name}")
91
+ _lazy[attr] = obj # Cache it
92
+ return obj
93
+
94
+ return _getattr, _all
95
+
96
+
97
+
98
+ # %% Test function run
99
+ if __name__ == "__main__":
100
+ from corelp import test
101
+ test(__file__)
File without changes
@@ -0,0 +1,80 @@
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 : kwargsself
8
+
9
+ """
10
+ This function will return all the attributes of an object (self) into a dictionnary (kwargs)
11
+ """
12
+
13
+
14
+
15
+ # %% Function
16
+ def kwargsself(self) :
17
+ '''
18
+ This function will return all the attributes of an object (self) into a dictionnary (kwargs)
19
+
20
+ Parameters
21
+ ----------
22
+ self : object
23
+ Object instance where to retrieve attributs.
24
+
25
+ Returns
26
+ -------
27
+ kwargs : dict
28
+ Dictionnary containing all the attributes and values.
29
+
30
+ Raises
31
+ ------
32
+ TypeError
33
+ If instance has not __dict__ nore __slots__ attributes.
34
+
35
+ Examples
36
+ --------
37
+ >>> from corelp import selfkwargs, kwargsself
38
+ ...
39
+ >>> # Typicall use is to store instance's state :
40
+ >>> class MyClass :
41
+ ... def __init__(self, **kwargs) :
42
+ ... selkwargs(self, kwargs) # Sets all the keyword arguments to self
43
+ ...
44
+ >>> instance = MyClass(a=1, b=2)
45
+ >>> print(instance.a)
46
+ 1
47
+ >>> print(instance.b)
48
+ 2
49
+ ...
50
+ >>> # Store state
51
+ >>> kwargs = kwargsself(instance)
52
+ >>> print(kwargs)
53
+ {"a": 1, "b": 2}
54
+ ...
55
+ >>> # Change state
56
+ >>> instance.a = 0
57
+ >>> print(instance.a)
58
+ 0
59
+ ...
60
+ >>> # Restore state
61
+ >>> selfkwargs(instance, kwargs)
62
+ >>> print(instance.a)
63
+ 1
64
+ '''
65
+
66
+ if hasattr(self, "__dict__") :
67
+ return {key: value for key, value in self.__dict__.items()}
68
+
69
+ elif hasattr(self, "__slots__") :
70
+ return {key : getattr(self, key) for key in self.__slots__}
71
+
72
+ else :
73
+ raise TypeError('Object has not __dict__ nore __slots__')
74
+
75
+
76
+
77
+ # %% Test function run
78
+ if __name__ == "__main__":
79
+ from corelp import test
80
+ test(__file__)
@@ -0,0 +1,59 @@
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 : kwargsself
8
+
9
+ """
10
+ This file allows to test kwargsself
11
+
12
+ kwargsself : This function will return all the attributes of an object (self) into a dictionnary (kwargs)
13
+ """
14
+
15
+
16
+
17
+ # %% Libraries
18
+ from corelp import debug, kwargsself, selfkwargs
19
+ from dataclasses import dataclass, field
20
+ import pytest
21
+ debug_folder = debug(__file__)
22
+
23
+
24
+
25
+ # %% Class test
26
+ def test_class() :
27
+ '''
28
+ Test kwargsself on classes
29
+ '''
30
+ class MyClass :
31
+ def __init__(self, **kwargs) :
32
+ selfkwargs(self, kwargs)
33
+ dic = {"a":"a", "b":"b"}
34
+ instance = MyClass(**dic)
35
+ kwargs = kwargsself(instance)
36
+ assert kwargs == dic
37
+
38
+
39
+
40
+ # %% Dataclass test
41
+ def test_dataclass() :
42
+ '''
43
+ Test kwargsself on dataclasses
44
+ '''
45
+ @dataclass(slots=True, kw_only=True)
46
+ class MyDataClass :
47
+ a: str = "a"
48
+ b : str = "b"
49
+ dic = {"a":"a", "b":"b"}
50
+ instance = MyDataClass()
51
+ kwargs = kwargsself(instance)
52
+ assert kwargs == dic
53
+
54
+
55
+
56
+ # %% Test function run
57
+ if __name__ == "__main__":
58
+ from corelp import test
59
+ test(__file__)
File without changes
@@ -0,0 +1,237 @@
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
+ run_name : str or None
55
+ Prefix to use for the output folder, if None takes the name of function decorated.
56
+
57
+ Examples
58
+ --------
59
+ >>> from corelp import main
60
+ ...
61
+ >>> import_path = None # will be asked via a GUI
62
+ >>> export_path = None # will create inside import_path
63
+ >>> new = False # True to create a new export folder, False to reload precalculated data
64
+ >>> bulk = None # function(import_path) that returns a dictionnary of {import_subfolder:export_subfolder} for multiple decorated function run.
65
+ >>> overnight= False # If True and exception occurs, will skip and pass to the next run in bulk processing.
66
+ >>> main_string = "Hello from main!" # User input parameter
67
+ ...
68
+ >>> @main(new=True) # if previous new is not defined, new is defined here
69
+ ... def myscript() :
70
+ ... print(main_string) # By default prints "Hello from main!"
71
+ ... result = mysection() # Section defined bellow, result can be reloaded from previous run
72
+ ... return result
73
+ ...
74
+ ... @main.section()
75
+ ... def mysection() :
76
+ ... print("Hello from section!")
77
+ ... return True # Will be saved into export_path and can be reuploaded at next run with same inputs
78
+ ...
79
+ >>> # Launch
80
+ >>> if __name__ == "__main__" :
81
+ ... myscript() # prints "Hello from main!"
82
+ ... myscript(main_string = "Hello changed!!") # prints "Hello changed!!" and loads section result from first run
83
+ '''
84
+
85
+
86
+
87
+ def decorator(func) :
88
+ name = func.__name__
89
+
90
+ # Get globals around function definition
91
+ definition_globals = func.__globals__
92
+
93
+ @functools.wraps(func)
94
+ def wrapper(**overrides) -> None :
95
+
96
+ # Creates new globals
97
+ exec_globals = definition_globals.copy()
98
+ exec_globals.update(overrides)
99
+ _new = exec_globals.get("new", False)
100
+ _bulk = exec_globals.get("bulk", None)
101
+ _overnight = exec_globals.get("overnight", False)
102
+
103
+ # Creates new function
104
+ new_func = types.FunctionType(
105
+ func.__code__,
106
+ exec_globals,
107
+ name=name,
108
+ argdefs=func.__defaults__,
109
+ closure=func.__closure__,
110
+ )
111
+
112
+ # Getting paths
113
+ ipath = exec_globals.get('import_path', "None")
114
+ if ipath is None :
115
+ root = tk.Tk()
116
+ root.title("Select import path")
117
+ root.iconbitmap(default=icon)
118
+ root.withdraw()
119
+ ipath = filedialog.askdirectory(title=f'Select import path for {name}')
120
+ root.destroy()
121
+ if not ipath :
122
+ print('Searching for import_path was cancelled', style='red')
123
+ raise ValueError('Searching for import_path was cancelled')
124
+ epath = exec_globals.get('export_path', "None")
125
+ if epath is None :
126
+ epath = ipath
127
+ if ipath != "None" :
128
+ ipath = Path(ipath)
129
+ if epath != "None" :
130
+ epath = Path(epath)
131
+
132
+ # Creating new export path
133
+ prefix = name.replace('.', '_')
134
+ if epath != "None" :
135
+ if _new :
136
+ epath = folder(epath / (f'{prefix}_' + datetime.now().strftime("%Y-%m-%d-%Hh%Mmin%Ss")), warning=False)
137
+ else :
138
+ #Searching for newest old folder
139
+ efolder = None
140
+ _date = None
141
+ for f in epath.iterdir() :
142
+ if (not f.is_dir()) or (not f.name.startswith(f'{prefix}_')) :
143
+ continue
144
+ date_str = f.name.split('_')[-1]
145
+ date = datetime.strptime(date_str, "%Y-%m-%d-%Hh%Mmin%Ss")
146
+ if _date is None or date > _date :
147
+ _date, efolder = date, f
148
+ epath = efolder if efolder is not None else epath / (f'{prefix}_' + datetime.now().strftime("%Y-%m-%d-%Hh%Mmin%Ss"))
149
+ if not epath.exists():
150
+ os.makedirs(epath) #creates folders until end
151
+ md_file = epath / (name+'_log.md')
152
+ html_file = epath / (name+'_log.html')
153
+ else :
154
+ md_file = None
155
+ html_file = None
156
+
157
+ # Defining bulk processing
158
+ if _bulk is None :
159
+ subfolders = {"" : ""}
160
+ else :
161
+ subfolders = _bulk(ipath)
162
+
163
+ #Begining prints
164
+ print_status = kwargsself(print)
165
+ print.console = None
166
+ print.file = md_file
167
+ print(f'\n\n\n# BEGIN {name}\n')
168
+ print(f"{time.ctime()}")
169
+ if ipath != "None" :
170
+ print(f'import_path : {ipath}\n')
171
+ if epath != "None" :
172
+ print(f'export_path : {epath}\n')
173
+
174
+ # Bulk processing
175
+ results = {} # {export_subfolder : fucntion result}
176
+ for import_subfolder, export_subfolder in subfolders.items() :
177
+ if ipath != "None" :
178
+ impath = ipath / import_subfolder
179
+ exec_globals["import_path"] = impath
180
+ if epath != "None" :
181
+ expath = epath / export_subfolder
182
+ exec_globals["export_path"] = expath
183
+
184
+ # Create export subfolder
185
+ if not expath.exists() :
186
+ os.mkdir(expath)
187
+
188
+ # Updating sections
189
+ wrapper.section.parent_path = epath
190
+ wrapper.section.path = expath
191
+ wrapper.section.new = _new
192
+
193
+ #Applying function
194
+ print("\n---\n")
195
+ subfolder_string = f"{export_subfolder}" if export_subfolder != "" else ""
196
+ print(f'## Launched script {subfolder_string}\n')
197
+ tic = time.perf_counter()
198
+ try :
199
+ results[export_subfolder] = new_func()
200
+
201
+ # Errors
202
+ except Exception as e :
203
+ toc = time.perf_counter()
204
+ print.error()
205
+ print(f'\n## **{subfolder_string} took {toc-tic:.2f}s**')
206
+ print("\n---\n")
207
+ if not _overnight :
208
+ raise e
209
+
210
+ # No error
211
+ else :
212
+ toc = time.perf_counter()
213
+ print(f'\n## **{subfolder_string} took {toc-tic:.2f}s**')
214
+ print("\n---\n")
215
+
216
+ # END
217
+ print(time.ctime())
218
+ print(f'# END {name}\n\n')
219
+ print.export_html(html_file)
220
+ selfkwargs(print, print_status)
221
+ if _bulk is None :
222
+ results = results[""]
223
+ return results
224
+
225
+ # Making sections
226
+ section = Section()
227
+ wrapper.section = section
228
+
229
+ return wrapper
230
+ return decorator
231
+
232
+
233
+
234
+ # %% Test function run
235
+ if __name__ == "__main__":
236
+ from corelp import test
237
+ test(__file__)
@@ -0,0 +1,74 @@
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