minor-utils 0.1.1__tar.gz → 0.2.0.dev1__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.
- minor_utils-0.2.0.dev1/PKG-INFO +8 -0
- {minor_utils-0.1.1 → minor_utils-0.2.0.dev1}/minor_utils/__init__.py +2 -0
- {minor_utils-0.1.1 → minor_utils-0.2.0.dev1}/minor_utils/formatter.py +73 -10
- minor_utils-0.2.0.dev1/minor_utils/func_manager.py +326 -0
- minor_utils-0.2.0.dev1/minor_utils.egg-info/PKG-INFO +8 -0
- {minor_utils-0.1.1 → minor_utils-0.2.0.dev1}/minor_utils.egg-info/SOURCES.txt +1 -1
- {minor_utils-0.1.1 → minor_utils-0.2.0.dev1}/pyproject.toml +1 -1
- minor_utils-0.1.1/PKG-INFO +0 -28
- minor_utils-0.1.1/README.md +0 -19
- minor_utils-0.1.1/minor_utils.egg-info/PKG-INFO +0 -28
- {minor_utils-0.1.1 → minor_utils-0.2.0.dev1}/minor_utils/errors.py +0 -0
- {minor_utils-0.1.1 → minor_utils-0.2.0.dev1}/minor_utils.egg-info/dependency_links.txt +0 -0
- {minor_utils-0.1.1 → minor_utils-0.2.0.dev1}/minor_utils.egg-info/top_level.txt +0 -0
- {minor_utils-0.1.1 → minor_utils-0.2.0.dev1}/setup.cfg +0 -0
|
@@ -4,10 +4,12 @@ __author__ = "Gleb Minor"
|
|
|
4
4
|
__license__ = "MIT"
|
|
5
5
|
|
|
6
6
|
from .formatter import Formatter
|
|
7
|
+
from .func_manager import Manager
|
|
7
8
|
from .errors import MissingStringError, InvalidArgumentError, FormatAlreadyExistsError, AliasAlreadyExistsError, DefaultFormatModificationError
|
|
8
9
|
|
|
9
10
|
__all__ = [
|
|
10
11
|
"Formatter",
|
|
12
|
+
"Manager",
|
|
11
13
|
"MissingStringError",
|
|
12
14
|
"InvalidArgumentError",
|
|
13
15
|
"FormatAlreadyExistsError",
|
|
@@ -5,7 +5,6 @@ from .errors import DefaultFormatModificationError, MissingStringError, InvalidA
|
|
|
5
5
|
|
|
6
6
|
class Formatter:
|
|
7
7
|
#--------(Format functions)--------
|
|
8
|
-
|
|
9
8
|
@staticmethod
|
|
10
9
|
def cap(s):
|
|
11
10
|
"""Capitalize the first character of the string and make the rest lowercase."""
|
|
@@ -89,7 +88,6 @@ class Formatter:
|
|
|
89
88
|
enabled_formats = list(formats.keys()) + list(format_aliases.keys())
|
|
90
89
|
|
|
91
90
|
#--------(Formatter function)--------
|
|
92
|
-
|
|
93
91
|
@classmethod
|
|
94
92
|
def get_callable(cls, string_format):
|
|
95
93
|
if string_format in cls.format_aliases:
|
|
@@ -109,7 +107,9 @@ class Formatter:
|
|
|
109
107
|
)
|
|
110
108
|
|
|
111
109
|
return func
|
|
110
|
+
#--------
|
|
112
111
|
|
|
112
|
+
#--------
|
|
113
113
|
@classmethod
|
|
114
114
|
def formatting(cls,
|
|
115
115
|
string: str,
|
|
@@ -144,6 +144,7 @@ class Formatter:
|
|
|
144
144
|
output = output[::-1]
|
|
145
145
|
|
|
146
146
|
return output
|
|
147
|
+
#--------
|
|
147
148
|
|
|
148
149
|
#--------(Pipeline API)--------
|
|
149
150
|
@classmethod
|
|
@@ -159,12 +160,13 @@ class Formatter:
|
|
|
159
160
|
for fmt in formats:
|
|
160
161
|
string = cls.formatting(string, fmt, inverse=inversed, reverse=reversed)
|
|
161
162
|
return string
|
|
163
|
+
#--------
|
|
162
164
|
|
|
163
165
|
#--------(Registry API)--------
|
|
164
166
|
@classmethod
|
|
165
167
|
def add_format(cls, func=None, name=None, *aliases):
|
|
166
168
|
def decorator(f):
|
|
167
|
-
cls.
|
|
169
|
+
cls.__validate_format_function(f)
|
|
168
170
|
|
|
169
171
|
format_name = (
|
|
170
172
|
name
|
|
@@ -205,10 +207,12 @@ class Formatter:
|
|
|
205
207
|
return decorator
|
|
206
208
|
|
|
207
209
|
return decorator(func)
|
|
210
|
+
#--------
|
|
208
211
|
|
|
212
|
+
#--------
|
|
209
213
|
@classmethod
|
|
210
214
|
def replace_format(cls, name, func):
|
|
211
|
-
cls.
|
|
215
|
+
cls.__validate_format_function(func)
|
|
212
216
|
|
|
213
217
|
if not cls.is_existing_format(name):
|
|
214
218
|
raise InvalidArgumentError(
|
|
@@ -221,7 +225,9 @@ class Formatter:
|
|
|
221
225
|
)
|
|
222
226
|
|
|
223
227
|
cls.formats[name] = func
|
|
228
|
+
#--------
|
|
224
229
|
|
|
230
|
+
#--------
|
|
225
231
|
@classmethod
|
|
226
232
|
def remove_format(cls, name):
|
|
227
233
|
if not cls.is_existing_format(name):
|
|
@@ -236,13 +242,17 @@ class Formatter:
|
|
|
236
242
|
|
|
237
243
|
cls.formats.pop(name, None)
|
|
238
244
|
cls.custom_formats.pop(name, None)
|
|
245
|
+
#--------
|
|
239
246
|
|
|
247
|
+
#--------
|
|
240
248
|
@classmethod
|
|
241
249
|
def reset_formats(cls):
|
|
242
250
|
cls.clear_aliases()
|
|
243
251
|
cls.clear_custom_formats()
|
|
244
252
|
cls.formats = cls.default_formats.copy()
|
|
253
|
+
#--------
|
|
245
254
|
|
|
255
|
+
#--------
|
|
246
256
|
@classmethod
|
|
247
257
|
def restore_format(cls, name):
|
|
248
258
|
if name not in cls.default_formats:
|
|
@@ -259,14 +269,18 @@ class Formatter:
|
|
|
259
269
|
cls.custom_formats.pop(name, None)
|
|
260
270
|
if name not in cls.enabled_formats:
|
|
261
271
|
cls.enabled_formats.append(name)
|
|
272
|
+
#--------
|
|
262
273
|
|
|
274
|
+
#--------
|
|
263
275
|
@classmethod
|
|
264
276
|
def clear_formats(cls):
|
|
265
277
|
cls.formats.clear()
|
|
266
278
|
cls.custom_formats.clear()
|
|
267
279
|
cls.enabled_formats.clear()
|
|
268
280
|
cls.format_aliases.clear()
|
|
281
|
+
#--------
|
|
269
282
|
|
|
283
|
+
#--------
|
|
270
284
|
@classmethod
|
|
271
285
|
def clear_default_formats(cls):
|
|
272
286
|
for name in list(cls.default_formats):
|
|
@@ -276,7 +290,9 @@ class Formatter:
|
|
|
276
290
|
cls.enabled_formats.remove(name)
|
|
277
291
|
|
|
278
292
|
cls.formats.pop(name, None)
|
|
293
|
+
#--------
|
|
279
294
|
|
|
295
|
+
#--------
|
|
280
296
|
@classmethod
|
|
281
297
|
def clear_custom_formats(cls):
|
|
282
298
|
for name in list(cls.custom_formats):
|
|
@@ -288,11 +304,15 @@ class Formatter:
|
|
|
288
304
|
cls.formats.pop(name, None)
|
|
289
305
|
|
|
290
306
|
cls.custom_formats.clear()
|
|
307
|
+
#--------
|
|
291
308
|
|
|
309
|
+
#--------
|
|
292
310
|
@classmethod
|
|
293
311
|
def get_formats(cls):
|
|
294
312
|
return cls.formats
|
|
313
|
+
#--------
|
|
295
314
|
|
|
315
|
+
#--------
|
|
296
316
|
@classmethod
|
|
297
317
|
def get_default_formats(cls):
|
|
298
318
|
return {
|
|
@@ -300,15 +320,21 @@ class Formatter:
|
|
|
300
320
|
for name in cls.formats
|
|
301
321
|
if name in cls.default_formats
|
|
302
322
|
}
|
|
323
|
+
#--------
|
|
303
324
|
|
|
325
|
+
#--------
|
|
304
326
|
@classmethod
|
|
305
327
|
def get_custom_formats(cls):
|
|
306
328
|
return cls.custom_formats
|
|
329
|
+
#--------
|
|
307
330
|
|
|
331
|
+
#--------
|
|
308
332
|
@classmethod
|
|
309
333
|
def get_builtin_formats(cls):
|
|
310
334
|
return cls.default_formats
|
|
335
|
+
#--------
|
|
311
336
|
|
|
337
|
+
#--------
|
|
312
338
|
@classmethod
|
|
313
339
|
def get_format_function(cls, name):
|
|
314
340
|
if not cls.is_existing_format(name):
|
|
@@ -317,7 +343,9 @@ class Formatter:
|
|
|
317
343
|
)
|
|
318
344
|
|
|
319
345
|
return cls.formats[name]
|
|
346
|
+
#--------
|
|
320
347
|
|
|
348
|
+
#--------
|
|
321
349
|
@classmethod
|
|
322
350
|
def names_of(cls, func):
|
|
323
351
|
names = []
|
|
@@ -329,7 +357,9 @@ class Formatter:
|
|
|
329
357
|
raise InvalidArgumentError(
|
|
330
358
|
f"Format {func.__name__} not found."
|
|
331
359
|
)
|
|
360
|
+
#--------
|
|
332
361
|
|
|
362
|
+
#--------
|
|
333
363
|
@classmethod
|
|
334
364
|
def get_format_info(cls, name):
|
|
335
365
|
if not cls.is_existing_format(name):
|
|
@@ -344,11 +374,15 @@ class Formatter:
|
|
|
344
374
|
"function": func,
|
|
345
375
|
"doc": func.__doc__
|
|
346
376
|
}
|
|
377
|
+
#--------
|
|
347
378
|
|
|
379
|
+
#--------
|
|
348
380
|
@classmethod
|
|
349
381
|
def get_format_doc(cls, name):
|
|
350
382
|
return cls.get_format_function(name).__doc__
|
|
383
|
+
#--------
|
|
351
384
|
|
|
385
|
+
#--------
|
|
352
386
|
@classmethod
|
|
353
387
|
def rename_format(cls, old_name, new_name):
|
|
354
388
|
if not cls.is_existing_format(old_name):
|
|
@@ -386,15 +420,21 @@ class Formatter:
|
|
|
386
420
|
|
|
387
421
|
for alias in aliases:
|
|
388
422
|
cls.format_aliases[alias] = func
|
|
423
|
+
#--------
|
|
389
424
|
|
|
425
|
+
#--------
|
|
390
426
|
@classmethod
|
|
391
427
|
def has_format(cls, name):
|
|
392
428
|
return cls.is_existing_format(name)
|
|
393
|
-
|
|
429
|
+
#--------
|
|
430
|
+
|
|
431
|
+
#--------
|
|
394
432
|
@classmethod
|
|
395
433
|
def has_alias(cls, name):
|
|
396
434
|
return cls.is_existing_alias(name)
|
|
435
|
+
#--------
|
|
397
436
|
|
|
437
|
+
#--------
|
|
398
438
|
@classmethod
|
|
399
439
|
def disable(cls, name):
|
|
400
440
|
if not cls.is_existing_format(name):
|
|
@@ -410,21 +450,25 @@ class Formatter:
|
|
|
410
450
|
|
|
411
451
|
if name in cls.enabled_formats:
|
|
412
452
|
cls.enabled_formats.remove(name)
|
|
453
|
+
#--------
|
|
413
454
|
|
|
455
|
+
#--------
|
|
414
456
|
@classmethod
|
|
415
457
|
def enable(cls, name):
|
|
416
458
|
if not cls.is_existing_format(name):
|
|
417
459
|
raise InvalidArgumentError(
|
|
418
460
|
f"Unable to enable format: format '{name}' does not exist."
|
|
419
461
|
)
|
|
420
|
-
|
|
462
|
+
|
|
421
463
|
aliases = list(cls.aliases_of(name))
|
|
422
464
|
if not cls.is_enabled(name):
|
|
423
465
|
cls.enabled_formats.append(name)
|
|
424
466
|
for alias in aliases:
|
|
425
467
|
if not cls.is_enabled(alias):
|
|
426
468
|
cls.enabled_formats.append(alias)
|
|
469
|
+
#--------
|
|
427
470
|
|
|
471
|
+
#--------
|
|
428
472
|
@classmethod
|
|
429
473
|
def toggle(cls, name):
|
|
430
474
|
if not cls.is_existing_format(name):
|
|
@@ -445,12 +489,13 @@ class Formatter:
|
|
|
445
489
|
for alias in aliases:
|
|
446
490
|
if alias not in cls.enabled_formats:
|
|
447
491
|
cls.enabled_formats.append(alias)
|
|
492
|
+
#--------
|
|
448
493
|
|
|
494
|
+
#--------
|
|
449
495
|
@classmethod
|
|
450
496
|
def is_enabled(cls, name):
|
|
451
497
|
return name in cls.enabled_formats
|
|
452
|
-
|
|
453
|
-
|
|
498
|
+
#--------
|
|
454
499
|
|
|
455
500
|
#--------(Validation API)--------
|
|
456
501
|
@classmethod
|
|
@@ -461,21 +506,28 @@ class Formatter:
|
|
|
461
506
|
"Input string is empty or contains only whitespace."
|
|
462
507
|
)
|
|
463
508
|
return s
|
|
509
|
+
#--------
|
|
464
510
|
|
|
511
|
+
#--------
|
|
465
512
|
@classmethod
|
|
466
513
|
def is_existing_format(cls, name):
|
|
467
514
|
return name in cls.formats
|
|
468
|
-
|
|
515
|
+
#--------
|
|
516
|
+
|
|
517
|
+
#--------
|
|
469
518
|
@classmethod
|
|
470
519
|
def is_existing_alias(cls, name):
|
|
471
520
|
return name in cls.format_aliases
|
|
521
|
+
#--------
|
|
472
522
|
|
|
523
|
+
#--------
|
|
473
524
|
@classmethod
|
|
474
|
-
def
|
|
525
|
+
def __validate_format_function(cls, func):
|
|
475
526
|
sig = signature(func)
|
|
476
527
|
|
|
477
528
|
if len(sig.parameters) != 1:
|
|
478
529
|
raise InvalidArgumentError("Format function must accept exactly one argument.")
|
|
530
|
+
#--------
|
|
479
531
|
|
|
480
532
|
#--------(Alias API)--------
|
|
481
533
|
|
|
@@ -501,7 +553,9 @@ class Formatter:
|
|
|
501
553
|
|
|
502
554
|
if alias_name not in cls.enabled_formats:
|
|
503
555
|
cls.enabled_formats.append(alias_name)
|
|
556
|
+
#--------
|
|
504
557
|
|
|
558
|
+
#--------
|
|
505
559
|
@classmethod
|
|
506
560
|
def del_alias(cls, alias_name):
|
|
507
561
|
if not cls.is_existing_alias(alias_name):
|
|
@@ -513,7 +567,9 @@ class Formatter:
|
|
|
513
567
|
cls.enabled_formats.remove(alias_name)
|
|
514
568
|
|
|
515
569
|
del cls.format_aliases[alias_name]
|
|
570
|
+
#--------
|
|
516
571
|
|
|
572
|
+
#--------
|
|
517
573
|
@classmethod
|
|
518
574
|
def del_aliases_of(cls, existing_name):
|
|
519
575
|
if not cls.is_existing_format(existing_name):
|
|
@@ -532,14 +588,18 @@ class Formatter:
|
|
|
532
588
|
cls.enabled_formats.remove(alias)
|
|
533
589
|
|
|
534
590
|
del cls.format_aliases[alias]
|
|
591
|
+
#--------
|
|
535
592
|
|
|
593
|
+
#--------
|
|
536
594
|
@classmethod
|
|
537
595
|
def clear_aliases(cls):
|
|
538
596
|
for alias in list(cls.format_aliases):
|
|
539
597
|
if alias in cls.enabled_formats:
|
|
540
598
|
cls.enabled_formats.remove(alias)
|
|
541
599
|
del cls.format_aliases[alias]
|
|
600
|
+
#--------
|
|
542
601
|
|
|
602
|
+
#--------
|
|
543
603
|
@classmethod
|
|
544
604
|
def aliases_of(cls, existing_name):
|
|
545
605
|
if not cls.is_existing_format(existing_name):
|
|
@@ -552,7 +612,10 @@ class Formatter:
|
|
|
552
612
|
for name, func in cls.format_aliases.items()
|
|
553
613
|
if func is cls.formats[existing_name] and name != existing_name
|
|
554
614
|
}
|
|
615
|
+
#--------
|
|
555
616
|
|
|
617
|
+
#--------
|
|
556
618
|
@classmethod
|
|
557
619
|
def get_all_aliases(cls):
|
|
558
620
|
return cls.format_aliases
|
|
621
|
+
#--------
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
# Errors
|
|
2
|
+
from .errors import InvalidArgumentError
|
|
3
|
+
|
|
4
|
+
class Manager:
|
|
5
|
+
managers = {}
|
|
6
|
+
counter = 0
|
|
7
|
+
|
|
8
|
+
#--------
|
|
9
|
+
def __init__(self, name=None):
|
|
10
|
+
|
|
11
|
+
self.__name = (
|
|
12
|
+
name
|
|
13
|
+
if name is not None
|
|
14
|
+
else "Manager"
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
self.__funcs = []
|
|
18
|
+
|
|
19
|
+
self.id = Manager.counter
|
|
20
|
+
Manager.counter += 1
|
|
21
|
+
Manager.managers[self.id] = self
|
|
22
|
+
#--------
|
|
23
|
+
|
|
24
|
+
#--------(Registration API)--------
|
|
25
|
+
def add_func(self, func=None, name=None, *args, **kwargs):
|
|
26
|
+
def decorator(f, *args, **kwargs):
|
|
27
|
+
self.__validate_func(func, *args, **kwargs)
|
|
28
|
+
|
|
29
|
+
if not self.validate_name(name):
|
|
30
|
+
raise InvalidArgumentError(f"Invalid function name '{name}'. Function names must be valid identifiers.")
|
|
31
|
+
|
|
32
|
+
func_name = (
|
|
33
|
+
name
|
|
34
|
+
if name is not None
|
|
35
|
+
else f.__name__
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
if self.is_existing_func(func_name):
|
|
39
|
+
raise InvalidArgumentError(f"Function '{func_name}' already exists in manager {self.__name}.")
|
|
40
|
+
|
|
41
|
+
self.__funcs.append(func_name, f)
|
|
42
|
+
|
|
43
|
+
return f
|
|
44
|
+
|
|
45
|
+
if func is None:
|
|
46
|
+
return decorator
|
|
47
|
+
|
|
48
|
+
return decorator(func)
|
|
49
|
+
|
|
50
|
+
def del_func(self, name):
|
|
51
|
+
if not self.is_existing_func(name):
|
|
52
|
+
raise InvalidArgumentError(f"Function '{name}' does not exist in manager {self.__name}.")
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
func_id = int(name)
|
|
56
|
+
del self.__funcs[func_id]
|
|
57
|
+
except (ValueError, TypeError):
|
|
58
|
+
for i, (func_name, _) in enumerate(self.__funcs):
|
|
59
|
+
if func_name == name:
|
|
60
|
+
del self.__funcs[i]
|
|
61
|
+
break
|
|
62
|
+
|
|
63
|
+
#--------
|
|
64
|
+
|
|
65
|
+
#--------(Lookup API)--------
|
|
66
|
+
def get_func(self, name):
|
|
67
|
+
if not self.is_existing_func(name):
|
|
68
|
+
raise InvalidArgumentError(f"Function '{name}' does not exist in manager {self.__name}.")
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
func_id = int(name)
|
|
72
|
+
return self.__funcs[func_id][1]
|
|
73
|
+
except (ValueError, TypeError):
|
|
74
|
+
for func_name, func in self.__funcs:
|
|
75
|
+
if func_name == name:
|
|
76
|
+
return func
|
|
77
|
+
#--------
|
|
78
|
+
|
|
79
|
+
#--------
|
|
80
|
+
def find_func(self, name):
|
|
81
|
+
if not self.is_existing_func(name):
|
|
82
|
+
return None
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
func_id = int(name)
|
|
86
|
+
return self.__funcs[func_id][1]
|
|
87
|
+
except (ValueError, TypeError):
|
|
88
|
+
for func_name, func in self.__funcs:
|
|
89
|
+
if func_name == name:
|
|
90
|
+
return func
|
|
91
|
+
#--------
|
|
92
|
+
|
|
93
|
+
#--------
|
|
94
|
+
def get_funcs(self):
|
|
95
|
+
return [func for _, func in self.__funcs]
|
|
96
|
+
#--------
|
|
97
|
+
|
|
98
|
+
#--------
|
|
99
|
+
def get_info(self, name = None):
|
|
100
|
+
if name is None:
|
|
101
|
+
return self.__funcs.copy()
|
|
102
|
+
else:
|
|
103
|
+
func = self.get_func(name)
|
|
104
|
+
return [func] if func is not None else []
|
|
105
|
+
#--------
|
|
106
|
+
|
|
107
|
+
#--------
|
|
108
|
+
def find_info(self, name = None):
|
|
109
|
+
if name is None:
|
|
110
|
+
return self.__funcs.copy()
|
|
111
|
+
else:
|
|
112
|
+
func = self.find_func(name)
|
|
113
|
+
return [func] if func is not None else []
|
|
114
|
+
#--------
|
|
115
|
+
|
|
116
|
+
#--------
|
|
117
|
+
def get_func_id(self, name):
|
|
118
|
+
if not self.is_existing_func(name):
|
|
119
|
+
raise InvalidArgumentError(f"Function '{name}' does not exist in manager {self.__name}.")
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
func_id = int(name)
|
|
123
|
+
return func_id
|
|
124
|
+
except (ValueError, TypeError):
|
|
125
|
+
for i, (func_name, _) in enumerate(self.__funcs):
|
|
126
|
+
if func_name == name:
|
|
127
|
+
return i
|
|
128
|
+
#--------
|
|
129
|
+
|
|
130
|
+
#--------
|
|
131
|
+
def get_func_name(self, name):
|
|
132
|
+
if not self.is_existing_func(name):
|
|
133
|
+
raise InvalidArgumentError(f"Function '{name}' does not exist in manager {self.__name}.")
|
|
134
|
+
|
|
135
|
+
try:
|
|
136
|
+
func_id = int(name)
|
|
137
|
+
return self.__funcs[func_id][0]
|
|
138
|
+
except (ValueError, TypeError):
|
|
139
|
+
for func_name, _ in self.__funcs:
|
|
140
|
+
if func_name == name:
|
|
141
|
+
return func_name
|
|
142
|
+
#--------
|
|
143
|
+
|
|
144
|
+
#--------
|
|
145
|
+
def get_ids(self):
|
|
146
|
+
return list(range(len(self.__funcs)))
|
|
147
|
+
#--------
|
|
148
|
+
|
|
149
|
+
#--------
|
|
150
|
+
def get_names(self):
|
|
151
|
+
return [func_name for func_name, _ in self.__funcs]
|
|
152
|
+
#--------
|
|
153
|
+
|
|
154
|
+
#--------
|
|
155
|
+
def info_to_string(self, name = None):
|
|
156
|
+
funcs = self.get_info(name)
|
|
157
|
+
output = ""
|
|
158
|
+
for i, (func_name, func) in enumerate(funcs):
|
|
159
|
+
output += (
|
|
160
|
+
f"--------\n"
|
|
161
|
+
f"ID = {i}\n"
|
|
162
|
+
f"Name = {func_name}\n"
|
|
163
|
+
f"Function = {func.__name__}\n"
|
|
164
|
+
)
|
|
165
|
+
output += "--------\n"
|
|
166
|
+
return output
|
|
167
|
+
#--------
|
|
168
|
+
|
|
169
|
+
#--------(Config API)--------
|
|
170
|
+
def compile_config(self, config=None):
|
|
171
|
+
ids = list(range(len(self.__funcs)))
|
|
172
|
+
|
|
173
|
+
if config is None:
|
|
174
|
+
return ids
|
|
175
|
+
|
|
176
|
+
env = {"ids": ids}
|
|
177
|
+
result = []
|
|
178
|
+
|
|
179
|
+
for expr in config:
|
|
180
|
+
if isinstance(expr, int):
|
|
181
|
+
result.append(expr)
|
|
182
|
+
continue
|
|
183
|
+
|
|
184
|
+
value = eval(expr, {}, env)
|
|
185
|
+
if isinstance(value, int):
|
|
186
|
+
result.append(value)
|
|
187
|
+
elif isinstance(value, (list, tuple)):
|
|
188
|
+
result.extend(value)
|
|
189
|
+
else:
|
|
190
|
+
raise InvalidArgumentError(f"Invalid config expression '{expr}'. Config expressions must evaluate to an integer or a list/tuple of integers.")
|
|
191
|
+
|
|
192
|
+
return result
|
|
193
|
+
#--------
|
|
194
|
+
|
|
195
|
+
#--------
|
|
196
|
+
def sample_menu(self):
|
|
197
|
+
menu = "--------Commands (ID: Name)--------\n" + "Note: commands are executed only by their IDs, not names.\n"
|
|
198
|
+
for i, func_name in enumerate(self.get_names()):
|
|
199
|
+
menu += f"{i}: {func_name}\n"
|
|
200
|
+
menu += "-1: Exit\n" + "-"*16 + "\n"
|
|
201
|
+
return menu
|
|
202
|
+
#--------
|
|
203
|
+
|
|
204
|
+
#--------
|
|
205
|
+
def sample_not_found_func(self, name):
|
|
206
|
+
if not self.is_id(name):
|
|
207
|
+
return f"Functions must be called by their IDs, not names. '{name}' is not an ID."
|
|
208
|
+
|
|
209
|
+
if not self.is_existing_func(name):
|
|
210
|
+
return f"Function '{name}' not found in manager {self.__name}."
|
|
211
|
+
#--------
|
|
212
|
+
|
|
213
|
+
#--------(Execution API)--------
|
|
214
|
+
def call_func(self, name, *args, safe = False, **kwargs):
|
|
215
|
+
if safe:
|
|
216
|
+
try:
|
|
217
|
+
return self.get_func(name)(*args, **kwargs)
|
|
218
|
+
except Exception as e:
|
|
219
|
+
print(f"Error occurred while calling function '{name}': {e}")
|
|
220
|
+
return None
|
|
221
|
+
else:
|
|
222
|
+
return self.get_func(name)(*args, **kwargs)
|
|
223
|
+
#--------
|
|
224
|
+
|
|
225
|
+
#--------
|
|
226
|
+
def run(self, *, config = None, arguments = None, safe = False):
|
|
227
|
+
order = self.compile_config(config)
|
|
228
|
+
|
|
229
|
+
if arguments is None:
|
|
230
|
+
arguments = [([], {}) for _ in self.__funcs]
|
|
231
|
+
|
|
232
|
+
if len(arguments) != len(self.__funcs):
|
|
233
|
+
raise InvalidArgumentError(f"Invalid arguments list. The number of argument sets must match the number of functions in the manager ({len(self.__funcs)}).")
|
|
234
|
+
|
|
235
|
+
results = []
|
|
236
|
+
|
|
237
|
+
for func_id in order:
|
|
238
|
+
args, kwargs = arguments[func_id]
|
|
239
|
+
|
|
240
|
+
result = self.call_func(func_id, safe = safe, *args, **kwargs)
|
|
241
|
+
results.append(result)
|
|
242
|
+
|
|
243
|
+
return results
|
|
244
|
+
#--------
|
|
245
|
+
|
|
246
|
+
#--------
|
|
247
|
+
def run_manual(self, *, arguments = None, safe = False, menu = None):
|
|
248
|
+
if menu is None:
|
|
249
|
+
menu = self.sample_menu()
|
|
250
|
+
else:
|
|
251
|
+
menu = str(menu) + "\n"
|
|
252
|
+
|
|
253
|
+
invalid_index_message = self.sample_not_found_func("{name}")
|
|
254
|
+
|
|
255
|
+
if arguments is None:
|
|
256
|
+
arguments = [([], {}) for _ in self.__funcs]
|
|
257
|
+
|
|
258
|
+
if len(arguments) != len(self.__funcs):
|
|
259
|
+
raise InvalidArgumentError(f"Invalid arguments list. The number of argument sets must match the number of functions in the manager ({len(self.__funcs)}).")
|
|
260
|
+
|
|
261
|
+
results = {}
|
|
262
|
+
|
|
263
|
+
while True:
|
|
264
|
+
print(menu)
|
|
265
|
+
choice = input("> ").strip()
|
|
266
|
+
|
|
267
|
+
if choice == "-1":
|
|
268
|
+
return results
|
|
269
|
+
|
|
270
|
+
if not self.is_id(choice) or not self.is_existing_func(choice):
|
|
271
|
+
print(invalid_index_message.format(name=choice))
|
|
272
|
+
continue
|
|
273
|
+
|
|
274
|
+
func_id = int(choice)
|
|
275
|
+
args, kwargs = arguments[func_id]
|
|
276
|
+
|
|
277
|
+
result = self.call_func(func_id, *args, safe = safe, **kwargs)
|
|
278
|
+
results.setdefault(func_id, []).append(result)
|
|
279
|
+
#--------
|
|
280
|
+
|
|
281
|
+
# --------(Validation API)--------
|
|
282
|
+
def is_existing_func(self, name):
|
|
283
|
+
try:
|
|
284
|
+
func_id = int(name)
|
|
285
|
+
return 0 <= func_id < len(self.__funcs)
|
|
286
|
+
except (ValueError, TypeError):
|
|
287
|
+
if not self.validate_name(name):
|
|
288
|
+
raise InvalidArgumentError(f"Invalid function identifier '{name}'. '{name}' must be a name or an integer index.")
|
|
289
|
+
|
|
290
|
+
for func_name, _ in self.__funcs:
|
|
291
|
+
if func_name == name:
|
|
292
|
+
return True
|
|
293
|
+
return False
|
|
294
|
+
#--------
|
|
295
|
+
|
|
296
|
+
#--------
|
|
297
|
+
def is_id(self, name):
|
|
298
|
+
try:
|
|
299
|
+
func_id = int(name)
|
|
300
|
+
return True
|
|
301
|
+
except (ValueError, TypeError):
|
|
302
|
+
return False
|
|
303
|
+
#--------
|
|
304
|
+
|
|
305
|
+
#--------
|
|
306
|
+
def is_name(self, name):
|
|
307
|
+
if self.validate_name(name):
|
|
308
|
+
return True
|
|
309
|
+
return False
|
|
310
|
+
#--------
|
|
311
|
+
|
|
312
|
+
#--------
|
|
313
|
+
@classmethod
|
|
314
|
+
def __validate_func(cls, func, *args, **kwargs):
|
|
315
|
+
try:
|
|
316
|
+
return func(*args, **kwargs)
|
|
317
|
+
except Exception as e:
|
|
318
|
+
raise InvalidArgumentError(f"Function '{func.__name__}' raised an error:\n{str(e)}") from e
|
|
319
|
+
#--------
|
|
320
|
+
|
|
321
|
+
#--------
|
|
322
|
+
@staticmethod
|
|
323
|
+
def validate_name(name):
|
|
324
|
+
name = str(name).strip()
|
|
325
|
+
return name.isidentifier()
|
|
326
|
+
#--------
|
minor_utils-0.1.1/PKG-INFO
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: minor_utils
|
|
3
|
-
Version: 0.1.1
|
|
4
|
-
Summary: Utils compilation for easier work
|
|
5
|
-
Author-email: CyberAxolotl <minor.gleb@outlook.com>
|
|
6
|
-
License-Expression: MIT
|
|
7
|
-
Requires-Python: >=3.10
|
|
8
|
-
Description-Content-Type: text/markdown
|
|
9
|
-
|
|
10
|
-
# minor-utils
|
|
11
|
-
|
|
12
|
-
Utility library for formatting and helper functions.
|
|
13
|
-
|
|
14
|
-
## Installation
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
pip install minor-utils
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## Note
|
|
21
|
-
|
|
22
|
-
The project is NOT final! It will be updated, new content will be added. There might be some bugs and information about the project is incomplete. You can use it now, but be careful. I recommend not to use it right now and wait untill it is finished.
|
|
23
|
-
|
|
24
|
-
## Where can I find it?
|
|
25
|
-
|
|
26
|
-
It is uploaded on PyPI
|
|
27
|
-
Link:
|
|
28
|
-
https://pypi.org/project/minor-utils/
|
minor_utils-0.1.1/README.md
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# minor-utils
|
|
2
|
-
|
|
3
|
-
Utility library for formatting and helper functions.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
pip install minor-utils
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Note
|
|
12
|
-
|
|
13
|
-
The project is NOT final! It will be updated, new content will be added. There might be some bugs and information about the project is incomplete. You can use it now, but be careful. I recommend not to use it right now and wait untill it is finished.
|
|
14
|
-
|
|
15
|
-
## Where can I find it?
|
|
16
|
-
|
|
17
|
-
It is uploaded on PyPI
|
|
18
|
-
Link:
|
|
19
|
-
https://pypi.org/project/minor-utils/
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: minor_utils
|
|
3
|
-
Version: 0.1.1
|
|
4
|
-
Summary: Utils compilation for easier work
|
|
5
|
-
Author-email: CyberAxolotl <minor.gleb@outlook.com>
|
|
6
|
-
License-Expression: MIT
|
|
7
|
-
Requires-Python: >=3.10
|
|
8
|
-
Description-Content-Type: text/markdown
|
|
9
|
-
|
|
10
|
-
# minor-utils
|
|
11
|
-
|
|
12
|
-
Utility library for formatting and helper functions.
|
|
13
|
-
|
|
14
|
-
## Installation
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
pip install minor-utils
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## Note
|
|
21
|
-
|
|
22
|
-
The project is NOT final! It will be updated, new content will be added. There might be some bugs and information about the project is incomplete. You can use it now, but be careful. I recommend not to use it right now and wait untill it is finished.
|
|
23
|
-
|
|
24
|
-
## Where can I find it?
|
|
25
|
-
|
|
26
|
-
It is uploaded on PyPI
|
|
27
|
-
Link:
|
|
28
|
-
https://pypi.org/project/minor-utils/
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|