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.
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: minor_utils
3
+ Version: 0.2.0.dev1
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
@@ -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.validate_format_function(f)
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.validate_format_function(func)
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 validate_format_function(cls, func):
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
+ #--------
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: minor_utils
3
+ Version: 0.2.0.dev1
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
@@ -1,8 +1,8 @@
1
- README.md
2
1
  pyproject.toml
3
2
  minor_utils/__init__.py
4
3
  minor_utils/errors.py
5
4
  minor_utils/formatter.py
5
+ minor_utils/func_manager.py
6
6
  minor_utils.egg-info/PKG-INFO
7
7
  minor_utils.egg-info/SOURCES.txt
8
8
  minor_utils.egg-info/dependency_links.txt
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "minor_utils"
7
- version = "0.1.1"
7
+ version = "0.2.0dev1"
8
8
  description = "Utils compilation for easier work"
9
9
  authors = [{name = "CyberAxolotl", email = "minor.gleb@outlook.com"}]
10
10
  license = "MIT"
@@ -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/
@@ -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