argenta 1.0.0b2__tar.gz → 1.0.1__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.
Files changed (83) hide show
  1. {argenta-1.0.0b2 → argenta-1.0.1}/.github/workflows/ruff.yml +1 -1
  2. {argenta-1.0.0b2 → argenta-1.0.1}/.gitignore +1 -1
  3. argenta-1.0.1/PKG-INFO +71 -0
  4. argenta-1.0.1/README.md +58 -0
  5. argenta-1.0.1/imgs/argenta_banner.png +0 -0
  6. argenta-1.0.1/imgs/argenta_logo.png +0 -0
  7. argenta-1.0.1/imgs/argenta_logo_strip.png +0 -0
  8. argenta-1.0.1/imgs/argenta_logo_strip.svg +46 -0
  9. {argenta-1.0.0b2 → argenta-1.0.1}/mock/default_mock_app/main.py +3 -2
  10. argenta-1.0.1/mock/local_test.py +89 -0
  11. argenta-1.0.1/mock/mock_app/handlers/handlers_implementation/help_command.py +12 -0
  12. {argenta-1.0.0b2 → argenta-1.0.1}/mock/mock_app/handlers/routers.py +10 -6
  13. {argenta-1.0.0b2 → argenta-1.0.1}/mock/mock_app/main.py +7 -4
  14. {argenta-1.0.0b2 → argenta-1.0.1}/pyproject.toml +1 -6
  15. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/app/autocompleter/entity.py +30 -11
  16. argenta-1.0.1/src/argenta/app/defaults.py +12 -0
  17. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/app/dividing_line/models.py +8 -10
  18. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/app/models.py +181 -114
  19. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/app/registered_routers/entity.py +1 -1
  20. argenta-1.0.1/src/argenta/command/__init__.py +3 -0
  21. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/command/exceptions.py +9 -2
  22. argenta-1.0.1/src/argenta/command/flag/defaults.py +31 -0
  23. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/command/flag/models.py +14 -11
  24. argenta-1.0.1/src/argenta/command/flags/__init__.py +16 -0
  25. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/command/flags/models.py +11 -8
  26. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/command/models.py +61 -36
  27. argenta-1.0.1/src/argenta/orchestrator/argparser/__init__.py +4 -0
  28. argenta-1.0.1/src/argenta/orchestrator/argparser/arguments/__init__.py +8 -0
  29. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/orchestrator/argparser/arguments/models.py +3 -2
  30. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/orchestrator/argparser/entity.py +22 -12
  31. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/orchestrator/entity.py +0 -1
  32. argenta-1.0.1/src/argenta/response/entity.py +29 -0
  33. argenta-1.0.1/src/argenta/response/status.py +8 -0
  34. argenta-1.0.1/src/argenta/router/__init__.py +4 -0
  35. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/router/command_handler/entity.py +1 -1
  36. argenta-1.0.1/src/argenta/router/defaults.py +4 -0
  37. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/router/entity.py +60 -60
  38. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/router/exceptions.py +4 -0
  39. {argenta-1.0.0b2 → argenta-1.0.1}/tests/system_tests/test_system_handling_non_standard_behavior.py +1 -1
  40. {argenta-1.0.0b2 → argenta-1.0.1}/tests/unit_tests/test_router.py +0 -4
  41. argenta-1.0.0b2/PKG-INFO +0 -1340
  42. argenta-1.0.0b2/README.md +0 -1327
  43. argenta-1.0.0b2/mock/local_test.py +0 -23
  44. argenta-1.0.0b2/mock/mock_app/handlers/handlers_implementation/help_command.py +0 -10
  45. argenta-1.0.0b2/src/argenta/app/defaults.py +0 -12
  46. argenta-1.0.0b2/src/argenta/command/__init__.py +0 -3
  47. argenta-1.0.0b2/src/argenta/command/flag/defaults.py +0 -24
  48. argenta-1.0.0b2/src/argenta/command/flags/__init__.py +0 -10
  49. argenta-1.0.0b2/src/argenta/orchestrator/argparser/__init__.py +0 -4
  50. argenta-1.0.0b2/src/argenta/orchestrator/argparser/arguments/__init__.py +0 -6
  51. argenta-1.0.0b2/src/argenta/response/entity.py +0 -27
  52. argenta-1.0.0b2/src/argenta/response/status.py +0 -9
  53. argenta-1.0.0b2/src/argenta/router/__init__.py +0 -4
  54. argenta-1.0.0b2/src/argenta/router/defaults.py +0 -4
  55. {argenta-1.0.0b2 → argenta-1.0.1}/.github/workflows/tests.yml +0 -0
  56. {argenta-1.0.0b2 → argenta-1.0.1}/LICENSE +0 -0
  57. {argenta-1.0.0b2 → argenta-1.0.1}/imgs/mock_app_preview1.png +0 -0
  58. {argenta-1.0.0b2 → argenta-1.0.1}/imgs/mock_app_preview2.png +0 -0
  59. {argenta-1.0.0b2 → argenta-1.0.1}/imgs/mock_app_preview3.png +0 -0
  60. {argenta-1.0.0b2 → argenta-1.0.1}/imgs/mock_app_preview4.png +0 -0
  61. {argenta-1.0.0b2 → argenta-1.0.1}/mock/__init__.py +0 -0
  62. {argenta-1.0.0b2 → argenta-1.0.1}/mock/default_mock_app/__init__.py +0 -0
  63. {argenta-1.0.0b2 → argenta-1.0.1}/mock/mock_app/__init__.py +0 -0
  64. {argenta-1.0.0b2 → argenta-1.0.1}/mock/mock_app/handlers/__init__.py +0 -0
  65. {argenta-1.0.0b2 → argenta-1.0.1}/mock/mock_app/handlers/handlers_implementation/__init__.py +0 -0
  66. {argenta-1.0.0b2 → argenta-1.0.1}/src/__init__.py +0 -0
  67. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/__init__.py +0 -0
  68. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/app/__init__.py +0 -0
  69. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/app/autocompleter/__init__.py +0 -0
  70. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/app/dividing_line/__init__.py +0 -0
  71. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/app/registered_routers/__init__.py +0 -0
  72. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/command/flag/__init__.py +0 -0
  73. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/orchestrator/__init__.py +0 -0
  74. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/response/__init__.py +0 -0
  75. {argenta-1.0.0b2 → argenta-1.0.1}/src/argenta/router/command_handler/__init__.py +0 -0
  76. {argenta-1.0.0b2 → argenta-1.0.1}/tests/__init__.py +0 -0
  77. {argenta-1.0.0b2 → argenta-1.0.1}/tests/system_tests/__init__.py +0 -0
  78. {argenta-1.0.0b2 → argenta-1.0.1}/tests/system_tests/test_system_handling_normal_behavior.py +0 -0
  79. {argenta-1.0.0b2 → argenta-1.0.1}/tests/unit_tests/__init__.py +0 -0
  80. {argenta-1.0.0b2 → argenta-1.0.1}/tests/unit_tests/test_app.py +0 -0
  81. {argenta-1.0.0b2 → argenta-1.0.1}/tests/unit_tests/test_command.py +0 -0
  82. {argenta-1.0.0b2 → argenta-1.0.1}/tests/unit_tests/test_dividing_line.py +0 -0
  83. {argenta-1.0.0b2 → argenta-1.0.1}/tests/unit_tests/test_flag.py +0 -0
@@ -27,4 +27,4 @@ jobs:
27
27
  pip install ruff
28
28
 
29
29
  - name: Run linter
30
- run: ruff check ./argenta
30
+ run: ruff check ./src
@@ -1,4 +1,4 @@
1
- .venv
1
+ *venv
2
2
  .idea
3
3
  dist
4
4
  uv.lock
argenta-1.0.1/PKG-INFO ADDED
@@ -0,0 +1,71 @@
1
+ Metadata-Version: 2.4
2
+ Name: argenta
3
+ Version: 1.0.1
4
+ Summary: Python library for building modular CLI applications
5
+ Author-email: kolo <kolo.is.main@gmail.com>
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: <4.0,>=3.11
9
+ Requires-Dist: art<7.0,>=6.4
10
+ Requires-Dist: pyreadline3>=3.5.4
11
+ Requires-Dist: rich<15.0.0,>=14.0.0
12
+ Description-Content-Type: text/markdown
13
+
14
+ # Argenta
15
+
16
+ ### Библиотека для создания модульных CLI приложeний
17
+
18
+ ![preview](https://github.com/koloideal/Argenta/blob/kolo/imgs/mock_app_preview4.png?raw=True)
19
+
20
+ ---
21
+
22
+ # Установка
23
+ ```bash
24
+ pip install argenta
25
+ ```
26
+ or
27
+ ```bash
28
+ poetry add argenta
29
+ ```
30
+
31
+ ---
32
+
33
+ # Быстрый старт
34
+
35
+ Пример простейшего приложения
36
+ ```python
37
+ # routers.py
38
+ from argenta.router import Router
39
+ from argenta.command import Command
40
+ from argenta.response import Response
41
+
42
+
43
+ router = Router()
44
+
45
+ @router.command(Command("hello"))
46
+ def handler(response: Response):
47
+ print("Hello, world!")
48
+ ```
49
+
50
+ ```python
51
+ # main.py
52
+ from argenta.app import App
53
+ from argenta.orchestrator import Orchestrator
54
+ from routers import router
55
+
56
+ app: App = App()
57
+ orchestrator: Orchestrator = Orchestrator()
58
+
59
+
60
+ def main() -> None:
61
+ app.include_router(router)
62
+ orchestrator.start_polling(app)
63
+
64
+
65
+ if __name__ == '__main__':
66
+ main()
67
+ ```
68
+ ## Полная [документация](https://argenta-docs.vercel.app) | MIT 2025 kolo | made by [kolo](https://t.me/kolo_id)
69
+
70
+
71
+
@@ -0,0 +1,58 @@
1
+ # Argenta
2
+
3
+ ### Библиотека для создания модульных CLI приложeний
4
+
5
+ ![preview](https://github.com/koloideal/Argenta/blob/kolo/imgs/mock_app_preview4.png?raw=True)
6
+
7
+ ---
8
+
9
+ # Установка
10
+ ```bash
11
+ pip install argenta
12
+ ```
13
+ or
14
+ ```bash
15
+ poetry add argenta
16
+ ```
17
+
18
+ ---
19
+
20
+ # Быстрый старт
21
+
22
+ Пример простейшего приложения
23
+ ```python
24
+ # routers.py
25
+ from argenta.router import Router
26
+ from argenta.command import Command
27
+ from argenta.response import Response
28
+
29
+
30
+ router = Router()
31
+
32
+ @router.command(Command("hello"))
33
+ def handler(response: Response):
34
+ print("Hello, world!")
35
+ ```
36
+
37
+ ```python
38
+ # main.py
39
+ from argenta.app import App
40
+ from argenta.orchestrator import Orchestrator
41
+ from routers import router
42
+
43
+ app: App = App()
44
+ orchestrator: Orchestrator = Orchestrator()
45
+
46
+
47
+ def main() -> None:
48
+ app.include_router(router)
49
+ orchestrator.start_polling(app)
50
+
51
+
52
+ if __name__ == '__main__':
53
+ main()
54
+ ```
55
+ ## Полная [документация](https://argenta-docs.vercel.app) | MIT 2025 kolo | made by [kolo](https://t.me/kolo_id)
56
+
57
+
58
+
Binary file
Binary file
@@ -0,0 +1,46 @@
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
3
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
4
+ <svg version="1.0" xmlns="http://www.w3.org/2000/svg"
5
+ width="809.000000pt" height="809.000000pt" viewBox="0 0 809.000000 809.000000"
6
+ preserveAspectRatio="xMidYMid meet">
7
+
8
+ <g transform="translate(0.000000,809.000000) scale(0.100000,-0.100000)"
9
+ fill="#000000" stroke="none">
10
+ <path d="M3845 7600 c-683 -38 -1333 -259 -1875 -639 -702 -492 -1223 -1251
11
+ -1434 -2089 -83 -330 -111 -602 -103 -980 6 -273 19 -393 67 -632 167 -829
12
+ 642 -1593 1321 -2122 512 -399 1133 -656 1794 -745 165 -22 666 -25 825 -5
13
+ 779 99 1451 397 2020 898 687 603 1095 1401 1201 2344 17 147 17 571 0 715
14
+ -59 518 -204 977 -442 1402 -180 322 -355 552 -629 823 -518 515 -1164 850
15
+ -1887 979 -254 45 -594 66 -858 51z m655 -234 c545 -76 1005 -248 1445 -541
16
+ 195 -130 336 -245 506 -415 457 -456 758 -987 909 -1605 134 -547 132 -1119
17
+ -5 -1665 -149 -593 -445 -1112 -885 -1550 -624 -623 -1414 -966 -2315 -1006
18
+ -412 -18 -935 73 -1339 232 -656 259 -1228 720 -1610 1299 -298 450 -461 890
19
+ -538 1451 -28 210 -31 620 -4 819 103 786 437 1477 975 2016 149 149 266 249
20
+ 417 357 315 225 692 405 1059 506 211 58 342 81 675 120 87 10 601 -3 710 -18z"/>
21
+ <path d="M3691 6759 c-231 -17 -522 -67 -660 -114 -227 -77 -354 -211 -381
22
+ -400 -14 -105 -13 -628 2 -643 9 -9 158 -12 611 -12 598 0 628 -2 649 -34 14
23
+ -21 8 -66 -12 -86 -20 -20 -33 -20 -908 -20 -857 0 -892 -1 -967 -20 -294 -75
24
+ -500 -321 -599 -715 -49 -195 -61 -309 -60 -585 0 -221 3 -272 23 -385 44
25
+ -251 116 -418 232 -540 78 -82 143 -123 254 -162 78 -27 85 -27 351 -31 l272
26
+ -4 16 23 c14 20 16 58 16 259 0 334 20 446 107 613 80 153 268 310 447 374
27
+ 128 45 138 46 881 52 683 7 713 8 786 28 201 56 353 177 437 348 80 162 86
28
+ 240 74 905 -11 608 -10 600 -84 743 -80 153 -240 271 -453 332 -252 73 -653
29
+ 101 -1034 74z m-383 -466 c126 -78 147 -245 44 -355 -144 -154 -396 -54 -395
30
+ 157 0 97 62 187 154 222 54 20 143 10 197 -24z"/>
31
+ <path d="M5451 5491 c-20 -20 -21 -30 -21 -283 0 -276 -7 -351 -42 -458 -81
32
+ -251 -281 -454 -523 -534 -149 -48 -151 -48 -890 -56 -678 -6 -703 -7 -780
33
+ -28 -139 -38 -219 -84 -315 -181 -61 -61 -95 -105 -117 -151 -65 -134 -64
34
+ -129 -75 -780 -12 -665 -10 -694 47 -817 122 -265 419 -429 895 -494 127 -18
35
+ 592 -18 730 -1 377 48 646 169 785 355 57 75 67 94 96 182 20 64 23 94 27 325
36
+ 4 238 3 257 -15 278 l-18 23 -551 -1 c-399 0 -559 3 -577 11 -51 23 -56 102
37
+ -8 126 9 4 439 10 956 13 1044 7 981 2 1125 75 178 89 305 255 386 502 84 257
38
+ 111 618 73 973 -39 364 -167 655 -351 801 -63 50 -121 80 -213 110 -64 20 -93
39
+ 23 -337 27 -260 4 -267 3 -287 -17z m-2104 -1698 c78 -52 531 -413 561 -447
40
+ 17 -19 33 -48 37 -65 15 -71 3 -84 -323 -356 -275 -229 -310 -255 -342 -255
41
+ -78 1 -112 75 -61 134 9 10 86 75 171 144 247 201 355 294 358 311 1 9 -15 28
42
+ -38 44 -127 89 -503 393 -512 413 -23 50 20 103 82 104 15 0 45 -12 67 -27z
43
+ m1388 -1244 c59 -15 129 -77 151 -134 36 -96 0 -204 -88 -262 -36 -24 -51 -28
44
+ -118 -28 -67 0 -82 4 -118 28 -153 101 -124 338 48 392 57 17 71 18 125 4z"/>
45
+ </g>
46
+ </svg>
@@ -8,8 +8,8 @@ from argenta.orchestrator.argparser import ArgParser
8
8
  from argenta.orchestrator.argparser.arguments import BooleanArgument
9
9
 
10
10
 
11
- arg_parser = ArgParser(processed_args=[BooleanArgument('repeat')])
12
- app: App = App(autocompleter=AutoCompleter('.hist'))
11
+ arg_parser = ArgParser(processed_args=[BooleanArgument("repeat")])
12
+ app: App = App(autocompleter=AutoCompleter(".hist"))
13
13
  orchestrator: Orchestrator = Orchestrator()
14
14
 
15
15
 
@@ -22,5 +22,6 @@ def main():
22
22
 
23
23
  orchestrator.start_polling(app)
24
24
 
25
+
25
26
  if __name__ == "__main__":
26
27
  main()
@@ -0,0 +1,89 @@
1
+ from argenta.app import App
2
+ from argenta.app.autocompleter import AutoCompleter
3
+ from argenta.router import Router
4
+ from argenta.command import Command
5
+ from argenta.orchestrator import Orchestrator
6
+ from argenta.app.dividing_line import DynamicDividingLine
7
+ from argenta.response import Response
8
+ import platform
9
+ import psutil
10
+ import os
11
+ import subprocess
12
+ import socket
13
+
14
+ # Маршрутизатор для работы с файлами
15
+ file_router = Router("Файловые операции")
16
+
17
+
18
+ @file_router.command(Command("list", "Список файлов"))
19
+ def list_files(response: Response):
20
+ files = os.listdir()
21
+ for file in files:
22
+ print(file)
23
+
24
+
25
+ @file_router.command(Command("size", "Размер файла"))
26
+ def file_size(response: Response):
27
+ file_name = input("Введите имя файла: ")
28
+ if os.path.exists(file_name):
29
+ size = os.path.getsize(file_name)
30
+ print(f"Размер файла {file_name}: {size} байт")
31
+ else:
32
+ print(f"Файл {file_name} не найден")
33
+
34
+
35
+ # Маршрутизатор для системных операций
36
+ system_router = Router("Системные операции")
37
+
38
+
39
+ @system_router.command(Command("info", "Информация о системе"))
40
+ def system_info(response: Response):
41
+ print(f"Система: {platform.system()}")
42
+ print(f"Версия: {platform.version()}")
43
+ print(f"Архитектура: {platform.architecture()}")
44
+ print(f"Процессор: {platform.processor()}")
45
+
46
+
47
+ @system_router.command(Command("memory", "Информация о памяти"))
48
+ def memory_info(response: Response):
49
+ memory = psutil.virtual_memory()
50
+ print(f"Всего памяти: {memory.total / (1024**3):.2f} ГБ")
51
+ print(f"Доступно: {memory.available / (1024**3):.2f} ГБ")
52
+ print(f"Использовано: {memory.used / (1024**3):.2f} ГБ ({memory.percent}%)")
53
+
54
+
55
+ # Маршрутизатор для сетевых операций
56
+ network_router = Router("Сетевые операции")
57
+
58
+
59
+ @network_router.command(Command("ping", "Проверка доступности хоста"))
60
+ def ping_host(response: Response):
61
+ host = input("Введите имя хоста: ")
62
+ print(f"Пингую {host}...")
63
+ subprocess.run(["ping", "-c", "4", host])
64
+
65
+
66
+ @network_router.command(Command("ip", "Показать IP-адреса"))
67
+ def show_ip(response: Response):
68
+ hostname = socket.gethostname()
69
+ print(f"Имя хоста: {hostname}")
70
+ print(f"IP-адрес: {socket.gethostbyname(hostname)}")
71
+
72
+
73
+ # Создание приложения и регистрация маршрутизаторов
74
+ app = App(
75
+ prompt="System> ",
76
+ initial_message="Pingator",
77
+ dividing_line=DynamicDividingLine("*"),
78
+ autocompleter=AutoCompleter(".hist", "e"),
79
+ )
80
+
81
+ # Добавляем все маршрутизаторы
82
+ app.include_routers(file_router, system_router, network_router)
83
+
84
+ # Добавляем сообщение при запуске
85
+ app.add_message_on_startup("Для просмотра доступных команд нажмите Enter")
86
+
87
+ # Запускаем приложение
88
+ orchestrator = Orchestrator()
89
+ orchestrator.start_polling(app)
@@ -0,0 +1,12 @@
1
+ from rich.console import Console
2
+
3
+
4
+ console = Console()
5
+
6
+
7
+ def help_command():
8
+ console.print(
9
+ "[italic bold]The main functionality of the script is to convert an expression from a string "
10
+ "to a mathematical one and then calculate this expression. "
11
+ "Project GitHub: https://github.com/koloideal/WordMath[/italic bold]"
12
+ )
@@ -7,12 +7,19 @@ from argenta.response import Response
7
7
  from argenta.router import Router
8
8
 
9
9
 
10
- work_router: Router = Router(title='Work points:')
10
+ work_router: Router = Router(title="Work points:")
11
11
 
12
12
  console = Console()
13
13
 
14
14
 
15
- @work_router.command(Command('get', 'Get Help', aliases=['help', 'Get_help'], flags=Flags(PredefinedFlags.PORT, PredefinedFlags.HOST)))
15
+ @work_router.command(
16
+ Command(
17
+ "get",
18
+ "Get Help",
19
+ aliases=["help", "Get_help"],
20
+ flags=Flags(PredefinedFlags.PORT, PredefinedFlags.HOST),
21
+ )
22
+ )
16
23
  def command_help(response: Response):
17
24
  print(response.status)
18
25
  print(response.undefined_flags.get_flags())
@@ -20,12 +27,9 @@ def command_help(response: Response):
20
27
  print(response.invalid_value_flags.get_flags())
21
28
 
22
29
 
23
- @work_router.command('run')
30
+ @work_router.command("run")
24
31
  def command_start_solving(response: Response):
25
32
  print(response.status)
26
33
  print(response.undefined_flags.get_flags())
27
34
  print(response.valid_flags.get_flags())
28
35
  print(response.invalid_value_flags.get_flags())
29
-
30
-
31
-
@@ -9,10 +9,12 @@ from argenta.orchestrator.argparser import ArgParser
9
9
  from argenta.orchestrator.argparser.arguments import BooleanArgument
10
10
 
11
11
 
12
- arg_parser = ArgParser(processed_args=[BooleanArgument('repeat')])
13
- app: App = App(dividing_line=DynamicDividingLine(),
14
- autocompleter=AutoCompleter('./mock/.hist'),
15
- repeat_command_groups=False,)
12
+ arg_parser = ArgParser(processed_args=[BooleanArgument("repeat")])
13
+ app: App = App(
14
+ dividing_line=DynamicDividingLine(),
15
+ autocompleter=AutoCompleter(),
16
+ repeat_command_groups=False,
17
+ )
16
18
  orchestrator: Orchestrator = Orchestrator(arg_parser)
17
19
 
18
20
 
@@ -25,5 +27,6 @@ def main():
25
27
 
26
28
  orchestrator.start_polling(app)
27
29
 
30
+
28
31
  if __name__ == "__main__":
29
32
  main()
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "argenta"
3
- version = "1.0.0-beta2"
3
+ version = "1.0.1"
4
4
  description = "Python library for building modular CLI applications"
5
5
  authors = [{ name = "kolo", email = "kolo.is.main@gmail.com" }]
6
6
  requires-python = ">=3.11, <4.0"
@@ -12,11 +12,6 @@ dependencies = [
12
12
  "pyreadline3>=3.5.4",
13
13
  ]
14
14
 
15
- [dependency-groups]
16
- dev = [
17
- "pydoc-markdown>=4.8.2,<5",
18
- ]
19
-
20
15
  [tool.ruff]
21
16
  exclude = [
22
17
  ".idea",
@@ -1,9 +1,12 @@
1
1
  import os
2
2
  import readline
3
+ from typing import Never
3
4
 
4
5
 
5
6
  class AutoCompleter:
6
- def __init__(self, history_filename: str = False, autocomplete_button: str = 'tab') -> None:
7
+ def __init__(
8
+ self, history_filename: str = False, autocomplete_button: str = "tab"
9
+ ) -> None:
7
10
  """
8
11
  Public. Configures and implements auto-completion of input command
9
12
  :param history_filename: the name of the file for saving the history of the autocompleter
@@ -12,7 +15,6 @@ class AutoCompleter:
12
15
  """
13
16
  self.history_filename = history_filename
14
17
  self.autocomplete_button = autocomplete_button
15
- self.matches: list[str] = []
16
18
 
17
19
  def _complete(self, text, state) -> str | None:
18
20
  """
@@ -21,16 +23,22 @@ class AutoCompleter:
21
23
  :param state: the current cursor position is relative to the beginning of the line
22
24
  :return: the desired candidate as str or None
23
25
  """
24
- matches: list[str] = sorted(cmd for cmd in self.get_history_items() if cmd.startswith(text))
26
+ matches: list[str] = sorted(
27
+ cmd for cmd in self.get_history_items() if cmd.startswith(text)
28
+ )
25
29
  if len(matches) > 1:
26
30
  common_prefix = matches[0]
27
31
  for match in matches[1:]:
28
32
  i = 0
29
- while i < len(common_prefix) and i < len(match) and common_prefix[i] == match[i]:
33
+ while (
34
+ i < len(common_prefix)
35
+ and i < len(match)
36
+ and common_prefix[i] == match[i]
37
+ ):
30
38
  i += 1
31
39
  common_prefix = common_prefix[:i]
32
40
  if state == 0:
33
- readline.insert_text(common_prefix[len(text):])
41
+ readline.insert_text(common_prefix[len(text) :])
34
42
  readline.redisplay()
35
43
  return None
36
44
  elif len(matches) == 1:
@@ -52,21 +60,32 @@ class AutoCompleter:
52
60
  readline.add_history(line)
53
61
 
54
62
  readline.set_completer(self._complete)
55
- readline.set_completer_delims(readline.get_completer_delims().replace(' ', ''))
56
- readline.parse_and_bind(f'{self.autocomplete_button}: complete')
63
+ readline.set_completer_delims(readline.get_completer_delims().replace(" ", ""))
64
+ readline.parse_and_bind(f"{self.autocomplete_button}: complete")
57
65
 
58
- def exit_setup(self) -> None:
66
+ def exit_setup(self, all_commands: list[str]) -> None:
59
67
  """
60
68
  Private. Exit setup function
61
69
  :return: None
62
70
  """
63
71
  if self.history_filename:
64
72
  readline.write_history_file(self.history_filename)
73
+ with open(self.history_filename, "r") as history_file:
74
+ raw_history = history_file.read()
75
+ pretty_history: list[str] = []
76
+ for line in set(raw_history.strip().split("\n")):
77
+ if line.split()[0] in all_commands:
78
+ pretty_history.append(line)
79
+ with open(self.history_filename, "w") as history_file:
80
+ history_file.write("\n".join(pretty_history))
65
81
 
66
82
  @staticmethod
67
- def get_history_items() -> list[str] | list:
83
+ def get_history_items() -> list[str] | list[Never]:
68
84
  """
69
85
  Private. Returns a list of all commands entered by the user
70
- :return: all commands entered by the user as list[str]
86
+ :return: all commands entered by the user as list[str] | list[Never]
71
87
  """
72
- return [readline.get_history_item(i) for i in range(1, readline.get_current_history_length() + 1)]
88
+ return [
89
+ readline.get_history_item(i)
90
+ for i in range(1, readline.get_current_history_length() + 1)
91
+ ]
@@ -0,0 +1,12 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass
5
+ class PredefinedMessages:
6
+ """
7
+ Public. A dataclass with predetermined messages for quick use
8
+ """
9
+
10
+ USAGE = "[b dim]Usage[/b dim]: [i]<command> <[green]flags[/green]>[/i]"
11
+ HELP = "[b dim]Help[/b dim]: [i]<command>[/i] [b red]--help[/b red]"
12
+ AUTOCOMPLETE = "[b dim]Autocomplete[/b dim]: [i]<part>[/i] [bold]<tab>"
@@ -2,7 +2,7 @@ from abc import ABC
2
2
 
3
3
 
4
4
  class BaseDividingLine(ABC):
5
- def __init__(self, unit_part: str = '-') -> None:
5
+ def __init__(self, unit_part: str = "-") -> None:
6
6
  """
7
7
  Private. The basic dividing line
8
8
  :param unit_part: the single part of the dividing line
@@ -16,13 +16,13 @@ class BaseDividingLine(ABC):
16
16
  :return: unit_part of dividing line as str
17
17
  """
18
18
  if len(self._unit_part) == 0:
19
- return ' '
19
+ return " "
20
20
  else:
21
21
  return self._unit_part[0]
22
22
 
23
23
 
24
24
  class StaticDividingLine(BaseDividingLine):
25
- def __init__(self, unit_part: str = '-', length: int = 25) -> None:
25
+ def __init__(self, unit_part: str = "-", length: int = 25) -> None:
26
26
  """
27
27
  Public. The static dividing line
28
28
  :param unit_part: the single part of the dividing line
@@ -39,13 +39,13 @@ class StaticDividingLine(BaseDividingLine):
39
39
  :return: full line of dividing line as str
40
40
  """
41
41
  if is_override:
42
- return f'\n{self.length * self.get_unit_part()}\n'
42
+ return f"\n{self.length * self.get_unit_part()}\n"
43
43
  else:
44
- return f'\n[dim]{self.length * self.get_unit_part()}[/dim]\n'
44
+ return f"\n[dim]{self.length * self.get_unit_part()}[/dim]\n"
45
45
 
46
46
 
47
47
  class DynamicDividingLine(BaseDividingLine):
48
- def __init__(self, unit_part: str = '-') -> None:
48
+ def __init__(self, unit_part: str = "-") -> None:
49
49
  """
50
50
  Public. The dynamic dividing line
51
51
  :param unit_part: the single part of the dividing line
@@ -61,8 +61,6 @@ class DynamicDividingLine(BaseDividingLine):
61
61
  :return: full line of dividing line as str
62
62
  """
63
63
  if is_override:
64
- return f'\n{length * self.get_unit_part()}\n'
64
+ return f"\n{length * self.get_unit_part()}\n"
65
65
  else:
66
- return f'\n[dim]{self.get_unit_part() * length}[/dim]\n'
67
-
68
-
66
+ return f"\n[dim]{self.get_unit_part() * length}[/dim]\n"