webscout 8.2.2__py3-none-any.whl → 2026.1.19__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.
- webscout/AIauto.py +524 -143
- webscout/AIbase.py +247 -123
- webscout/AIutel.py +68 -132
- webscout/Bard.py +1072 -535
- webscout/Extra/GitToolkit/__init__.py +2 -2
- webscout/Extra/GitToolkit/gitapi/__init__.py +20 -12
- webscout/Extra/GitToolkit/gitapi/gist.py +142 -0
- webscout/Extra/GitToolkit/gitapi/organization.py +91 -0
- webscout/Extra/GitToolkit/gitapi/repository.py +308 -195
- webscout/Extra/GitToolkit/gitapi/search.py +162 -0
- webscout/Extra/GitToolkit/gitapi/trending.py +236 -0
- webscout/Extra/GitToolkit/gitapi/user.py +128 -96
- webscout/Extra/GitToolkit/gitapi/utils.py +82 -62
- webscout/Extra/YTToolkit/README.md +443 -0
- webscout/Extra/YTToolkit/YTdownloader.py +953 -957
- webscout/Extra/YTToolkit/__init__.py +3 -3
- webscout/Extra/YTToolkit/transcriber.py +595 -476
- webscout/Extra/YTToolkit/ytapi/README.md +230 -0
- webscout/Extra/YTToolkit/ytapi/__init__.py +22 -6
- webscout/Extra/YTToolkit/ytapi/captions.py +190 -0
- webscout/Extra/YTToolkit/ytapi/channel.py +302 -307
- webscout/Extra/YTToolkit/ytapi/errors.py +13 -13
- webscout/Extra/YTToolkit/ytapi/extras.py +178 -45
- webscout/Extra/YTToolkit/ytapi/hashtag.py +120 -0
- webscout/Extra/YTToolkit/ytapi/https.py +89 -88
- webscout/Extra/YTToolkit/ytapi/patterns.py +61 -61
- webscout/Extra/YTToolkit/ytapi/playlist.py +59 -59
- webscout/Extra/YTToolkit/ytapi/pool.py +8 -8
- webscout/Extra/YTToolkit/ytapi/query.py +143 -40
- webscout/Extra/YTToolkit/ytapi/shorts.py +122 -0
- webscout/Extra/YTToolkit/ytapi/stream.py +68 -63
- webscout/Extra/YTToolkit/ytapi/suggestions.py +97 -0
- webscout/Extra/YTToolkit/ytapi/utils.py +66 -62
- webscout/Extra/YTToolkit/ytapi/video.py +189 -18
- webscout/Extra/__init__.py +2 -3
- webscout/Extra/gguf.py +1298 -682
- webscout/Extra/tempmail/README.md +488 -0
- webscout/Extra/tempmail/__init__.py +28 -28
- webscout/Extra/tempmail/async_utils.py +143 -141
- webscout/Extra/tempmail/base.py +172 -161
- webscout/Extra/tempmail/cli.py +191 -187
- webscout/Extra/tempmail/emailnator.py +88 -84
- webscout/Extra/tempmail/mail_tm.py +378 -361
- webscout/Extra/tempmail/temp_mail_io.py +304 -292
- webscout/Extra/weather.py +196 -194
- webscout/Extra/weather_ascii.py +17 -15
- webscout/Provider/AISEARCH/PERPLEXED_search.py +175 -0
- webscout/Provider/AISEARCH/Perplexity.py +237 -304
- webscout/Provider/AISEARCH/README.md +106 -0
- webscout/Provider/AISEARCH/__init__.py +16 -10
- webscout/Provider/AISEARCH/brave_search.py +298 -0
- webscout/Provider/AISEARCH/iask_search.py +130 -209
- webscout/Provider/AISEARCH/monica_search.py +200 -246
- webscout/Provider/AISEARCH/webpilotai_search.py +242 -281
- webscout/Provider/Algion.py +413 -0
- webscout/Provider/Andi.py +74 -69
- webscout/Provider/Apriel.py +313 -0
- webscout/Provider/Ayle.py +323 -0
- webscout/Provider/ChatSandbox.py +329 -0
- webscout/Provider/ClaudeOnline.py +365 -0
- webscout/Provider/Cohere.py +232 -208
- webscout/Provider/DeepAI.py +367 -0
- webscout/Provider/Deepinfra.py +343 -173
- webscout/Provider/EssentialAI.py +217 -0
- webscout/Provider/ExaAI.py +274 -261
- webscout/Provider/Gemini.py +60 -54
- webscout/Provider/GithubChat.py +385 -367
- webscout/Provider/Gradient.py +286 -0
- webscout/Provider/Groq.py +556 -670
- webscout/Provider/HadadXYZ.py +323 -0
- webscout/Provider/HeckAI.py +392 -233
- webscout/Provider/HuggingFace.py +387 -0
- webscout/Provider/IBM.py +340 -0
- webscout/Provider/Jadve.py +317 -266
- webscout/Provider/K2Think.py +306 -0
- webscout/Provider/Koboldai.py +221 -381
- webscout/Provider/Netwrck.py +273 -228
- webscout/Provider/Nvidia.py +310 -0
- webscout/Provider/OPENAI/DeepAI.py +489 -0
- webscout/Provider/OPENAI/K2Think.py +423 -0
- webscout/Provider/OPENAI/PI.py +463 -0
- webscout/Provider/OPENAI/README.md +890 -0
- webscout/Provider/OPENAI/TogetherAI.py +405 -0
- webscout/Provider/OPENAI/TwoAI.py +255 -0
- webscout/Provider/OPENAI/__init__.py +148 -25
- webscout/Provider/OPENAI/ai4chat.py +348 -0
- webscout/Provider/OPENAI/akashgpt.py +436 -0
- webscout/Provider/OPENAI/algion.py +303 -0
- webscout/Provider/OPENAI/ayle.py +365 -0
- webscout/Provider/OPENAI/base.py +253 -46
- webscout/Provider/OPENAI/cerebras.py +296 -0
- webscout/Provider/OPENAI/chatgpt.py +514 -193
- webscout/Provider/OPENAI/chatsandbox.py +233 -0
- webscout/Provider/OPENAI/deepinfra.py +403 -272
- webscout/Provider/OPENAI/e2b.py +2370 -1350
- webscout/Provider/OPENAI/elmo.py +278 -0
- webscout/Provider/OPENAI/exaai.py +186 -138
- webscout/Provider/OPENAI/freeassist.py +446 -0
- webscout/Provider/OPENAI/gradient.py +448 -0
- webscout/Provider/OPENAI/groq.py +380 -0
- webscout/Provider/OPENAI/hadadxyz.py +292 -0
- webscout/Provider/OPENAI/heckai.py +100 -104
- webscout/Provider/OPENAI/huggingface.py +321 -0
- webscout/Provider/OPENAI/ibm.py +425 -0
- webscout/Provider/OPENAI/llmchat.py +253 -0
- webscout/Provider/OPENAI/llmchatco.py +378 -327
- webscout/Provider/OPENAI/meta.py +541 -0
- webscout/Provider/OPENAI/netwrck.py +110 -84
- webscout/Provider/OPENAI/nvidia.py +317 -0
- webscout/Provider/OPENAI/oivscode.py +348 -0
- webscout/Provider/OPENAI/openrouter.py +328 -0
- webscout/Provider/OPENAI/pydantic_imports.py +1 -0
- webscout/Provider/OPENAI/sambanova.py +397 -0
- webscout/Provider/OPENAI/sonus.py +126 -115
- webscout/Provider/OPENAI/textpollinations.py +218 -133
- webscout/Provider/OPENAI/toolbaz.py +136 -166
- webscout/Provider/OPENAI/typefully.py +419 -0
- webscout/Provider/OPENAI/typliai.py +279 -0
- webscout/Provider/OPENAI/utils.py +314 -211
- webscout/Provider/OPENAI/wisecat.py +103 -125
- webscout/Provider/OPENAI/writecream.py +185 -156
- webscout/Provider/OPENAI/x0gpt.py +227 -136
- webscout/Provider/OPENAI/zenmux.py +380 -0
- webscout/Provider/OpenRouter.py +386 -0
- webscout/Provider/Openai.py +337 -496
- webscout/Provider/PI.py +443 -344
- webscout/Provider/QwenLM.py +346 -254
- webscout/Provider/STT/__init__.py +28 -0
- webscout/Provider/STT/base.py +303 -0
- webscout/Provider/STT/elevenlabs.py +264 -0
- webscout/Provider/Sambanova.py +317 -0
- webscout/Provider/TTI/README.md +69 -0
- webscout/Provider/TTI/__init__.py +37 -12
- webscout/Provider/TTI/base.py +147 -0
- webscout/Provider/TTI/claudeonline.py +393 -0
- webscout/Provider/TTI/magicstudio.py +292 -0
- webscout/Provider/TTI/miragic.py +180 -0
- webscout/Provider/TTI/pollinations.py +331 -0
- webscout/Provider/TTI/together.py +334 -0
- webscout/Provider/TTI/utils.py +14 -0
- webscout/Provider/TTS/README.md +186 -0
- webscout/Provider/TTS/__init__.py +43 -7
- webscout/Provider/TTS/base.py +523 -0
- webscout/Provider/TTS/deepgram.py +286 -156
- webscout/Provider/TTS/elevenlabs.py +189 -111
- webscout/Provider/TTS/freetts.py +218 -0
- webscout/Provider/TTS/murfai.py +288 -113
- webscout/Provider/TTS/openai_fm.py +364 -0
- webscout/Provider/TTS/parler.py +203 -111
- webscout/Provider/TTS/qwen.py +334 -0
- webscout/Provider/TTS/sherpa.py +286 -0
- webscout/Provider/TTS/speechma.py +693 -180
- webscout/Provider/TTS/streamElements.py +275 -333
- webscout/Provider/TTS/utils.py +280 -280
- webscout/Provider/TextPollinationsAI.py +221 -121
- webscout/Provider/TogetherAI.py +450 -0
- webscout/Provider/TwoAI.py +309 -199
- webscout/Provider/TypliAI.py +311 -0
- webscout/Provider/UNFINISHED/ChatHub.py +219 -0
- webscout/Provider/{OPENAI/glider.py → UNFINISHED/ChutesAI.py} +160 -145
- webscout/Provider/UNFINISHED/GizAI.py +300 -0
- webscout/Provider/UNFINISHED/Marcus.py +218 -0
- webscout/Provider/UNFINISHED/Qodo.py +481 -0
- webscout/Provider/UNFINISHED/XenAI.py +330 -0
- webscout/Provider/{Youchat.py → UNFINISHED/Youchat.py} +64 -47
- webscout/Provider/UNFINISHED/aihumanizer.py +41 -0
- webscout/Provider/UNFINISHED/grammerchecker.py +37 -0
- webscout/Provider/UNFINISHED/liner.py +342 -0
- webscout/Provider/UNFINISHED/liner_api_request.py +246 -0
- webscout/Provider/UNFINISHED/samurai.py +231 -0
- webscout/Provider/WiseCat.py +256 -196
- webscout/Provider/WrDoChat.py +390 -0
- webscout/Provider/__init__.py +115 -198
- webscout/Provider/ai4chat.py +181 -202
- webscout/Provider/akashgpt.py +330 -342
- webscout/Provider/cerebras.py +397 -242
- webscout/Provider/cleeai.py +236 -213
- webscout/Provider/elmo.py +291 -234
- webscout/Provider/geminiapi.py +343 -208
- webscout/Provider/julius.py +245 -223
- webscout/Provider/learnfastai.py +333 -266
- webscout/Provider/llama3mitril.py +230 -180
- webscout/Provider/llmchat.py +308 -213
- webscout/Provider/llmchatco.py +321 -311
- webscout/Provider/meta.py +996 -794
- webscout/Provider/oivscode.py +332 -0
- webscout/Provider/searchchat.py +316 -293
- webscout/Provider/sonus.py +264 -208
- webscout/Provider/toolbaz.py +359 -320
- webscout/Provider/turboseek.py +332 -219
- webscout/Provider/typefully.py +262 -280
- webscout/Provider/x0gpt.py +332 -256
- webscout/__init__.py +31 -38
- webscout/__main__.py +5 -5
- webscout/cli.py +585 -293
- webscout/client.py +1497 -0
- webscout/conversation.py +140 -565
- webscout/exceptions.py +383 -339
- webscout/litagent/__init__.py +29 -29
- webscout/litagent/agent.py +492 -455
- webscout/litagent/constants.py +60 -60
- webscout/models.py +505 -181
- webscout/optimizers.py +32 -378
- webscout/prompt_manager.py +376 -274
- webscout/sanitize.py +1514 -0
- webscout/scout/README.md +452 -0
- webscout/scout/__init__.py +8 -8
- webscout/scout/core/__init__.py +7 -7
- webscout/scout/core/crawler.py +330 -140
- webscout/scout/core/scout.py +800 -568
- webscout/scout/core/search_result.py +51 -96
- webscout/scout/core/text_analyzer.py +64 -63
- webscout/scout/core/text_utils.py +412 -277
- webscout/scout/core/web_analyzer.py +54 -52
- webscout/scout/element.py +872 -460
- webscout/scout/parsers/__init__.py +70 -69
- webscout/scout/parsers/html5lib_parser.py +182 -172
- webscout/scout/parsers/html_parser.py +238 -236
- webscout/scout/parsers/lxml_parser.py +203 -178
- webscout/scout/utils.py +38 -37
- webscout/search/__init__.py +47 -0
- webscout/search/base.py +201 -0
- webscout/search/bing_main.py +45 -0
- webscout/search/brave_main.py +92 -0
- webscout/search/duckduckgo_main.py +57 -0
- webscout/search/engines/__init__.py +127 -0
- webscout/search/engines/bing/__init__.py +15 -0
- webscout/search/engines/bing/base.py +35 -0
- webscout/search/engines/bing/images.py +114 -0
- webscout/search/engines/bing/news.py +96 -0
- webscout/search/engines/bing/suggestions.py +36 -0
- webscout/search/engines/bing/text.py +109 -0
- webscout/search/engines/brave/__init__.py +19 -0
- webscout/search/engines/brave/base.py +47 -0
- webscout/search/engines/brave/images.py +213 -0
- webscout/search/engines/brave/news.py +353 -0
- webscout/search/engines/brave/suggestions.py +318 -0
- webscout/search/engines/brave/text.py +167 -0
- webscout/search/engines/brave/videos.py +364 -0
- webscout/search/engines/duckduckgo/__init__.py +25 -0
- webscout/search/engines/duckduckgo/answers.py +80 -0
- webscout/search/engines/duckduckgo/base.py +189 -0
- webscout/search/engines/duckduckgo/images.py +100 -0
- webscout/search/engines/duckduckgo/maps.py +183 -0
- webscout/search/engines/duckduckgo/news.py +70 -0
- webscout/search/engines/duckduckgo/suggestions.py +22 -0
- webscout/search/engines/duckduckgo/text.py +221 -0
- webscout/search/engines/duckduckgo/translate.py +48 -0
- webscout/search/engines/duckduckgo/videos.py +80 -0
- webscout/search/engines/duckduckgo/weather.py +84 -0
- webscout/search/engines/mojeek.py +61 -0
- webscout/search/engines/wikipedia.py +77 -0
- webscout/search/engines/yahoo/__init__.py +41 -0
- webscout/search/engines/yahoo/answers.py +19 -0
- webscout/search/engines/yahoo/base.py +34 -0
- webscout/search/engines/yahoo/images.py +323 -0
- webscout/search/engines/yahoo/maps.py +19 -0
- webscout/search/engines/yahoo/news.py +258 -0
- webscout/search/engines/yahoo/suggestions.py +140 -0
- webscout/search/engines/yahoo/text.py +273 -0
- webscout/search/engines/yahoo/translate.py +19 -0
- webscout/search/engines/yahoo/videos.py +302 -0
- webscout/search/engines/yahoo/weather.py +220 -0
- webscout/search/engines/yandex.py +67 -0
- webscout/search/engines/yep/__init__.py +13 -0
- webscout/search/engines/yep/base.py +34 -0
- webscout/search/engines/yep/images.py +101 -0
- webscout/search/engines/yep/suggestions.py +38 -0
- webscout/search/engines/yep/text.py +99 -0
- webscout/search/http_client.py +172 -0
- webscout/search/results.py +141 -0
- webscout/search/yahoo_main.py +57 -0
- webscout/search/yep_main.py +48 -0
- webscout/server/__init__.py +48 -0
- webscout/server/config.py +78 -0
- webscout/server/exceptions.py +69 -0
- webscout/server/providers.py +286 -0
- webscout/server/request_models.py +131 -0
- webscout/server/request_processing.py +404 -0
- webscout/server/routes.py +642 -0
- webscout/server/server.py +351 -0
- webscout/server/ui_templates.py +1171 -0
- webscout/swiftcli/__init__.py +79 -809
- webscout/swiftcli/core/__init__.py +7 -0
- webscout/swiftcli/core/cli.py +574 -0
- webscout/swiftcli/core/context.py +98 -0
- webscout/swiftcli/core/group.py +268 -0
- webscout/swiftcli/decorators/__init__.py +28 -0
- webscout/swiftcli/decorators/command.py +243 -0
- webscout/swiftcli/decorators/options.py +247 -0
- webscout/swiftcli/decorators/output.py +392 -0
- webscout/swiftcli/exceptions.py +21 -0
- webscout/swiftcli/plugins/__init__.py +9 -0
- webscout/swiftcli/plugins/base.py +134 -0
- webscout/swiftcli/plugins/manager.py +269 -0
- webscout/swiftcli/utils/__init__.py +58 -0
- webscout/swiftcli/utils/formatting.py +251 -0
- webscout/swiftcli/utils/parsing.py +368 -0
- webscout/update_checker.py +280 -136
- webscout/utils.py +28 -14
- webscout/version.py +2 -1
- webscout/version.py.bak +3 -0
- webscout/zeroart/__init__.py +218 -55
- webscout/zeroart/base.py +70 -60
- webscout/zeroart/effects.py +155 -99
- webscout/zeroart/fonts.py +1799 -816
- webscout-2026.1.19.dist-info/METADATA +638 -0
- webscout-2026.1.19.dist-info/RECORD +312 -0
- {webscout-8.2.2.dist-info → webscout-2026.1.19.dist-info}/WHEEL +1 -1
- webscout-2026.1.19.dist-info/entry_points.txt +4 -0
- webscout-2026.1.19.dist-info/top_level.txt +1 -0
- inferno/__init__.py +0 -6
- inferno/__main__.py +0 -9
- inferno/cli.py +0 -6
- webscout/DWEBS.py +0 -477
- webscout/Extra/autocoder/__init__.py +0 -9
- webscout/Extra/autocoder/autocoder.py +0 -849
- webscout/Extra/autocoder/autocoder_utiles.py +0 -332
- webscout/LLM.py +0 -442
- webscout/Litlogger/__init__.py +0 -67
- webscout/Litlogger/core/__init__.py +0 -6
- webscout/Litlogger/core/level.py +0 -23
- webscout/Litlogger/core/logger.py +0 -165
- webscout/Litlogger/handlers/__init__.py +0 -12
- webscout/Litlogger/handlers/console.py +0 -33
- webscout/Litlogger/handlers/file.py +0 -143
- webscout/Litlogger/handlers/network.py +0 -173
- webscout/Litlogger/styles/__init__.py +0 -7
- webscout/Litlogger/styles/colors.py +0 -249
- webscout/Litlogger/styles/formats.py +0 -458
- webscout/Litlogger/styles/text.py +0 -87
- webscout/Litlogger/utils/__init__.py +0 -6
- webscout/Litlogger/utils/detectors.py +0 -153
- webscout/Litlogger/utils/formatters.py +0 -200
- webscout/Local/__init__.py +0 -12
- webscout/Local/__main__.py +0 -9
- webscout/Local/api.py +0 -576
- webscout/Local/cli.py +0 -516
- webscout/Local/config.py +0 -75
- webscout/Local/llm.py +0 -287
- webscout/Local/model_manager.py +0 -253
- webscout/Local/server.py +0 -721
- webscout/Local/utils.py +0 -93
- webscout/Provider/AI21.py +0 -177
- webscout/Provider/AISEARCH/DeepFind.py +0 -250
- webscout/Provider/AISEARCH/ISou.py +0 -256
- webscout/Provider/AISEARCH/felo_search.py +0 -228
- webscout/Provider/AISEARCH/genspark_search.py +0 -208
- webscout/Provider/AISEARCH/hika_search.py +0 -194
- webscout/Provider/AISEARCH/scira_search.py +0 -324
- webscout/Provider/Aitopia.py +0 -292
- webscout/Provider/AllenAI.py +0 -413
- webscout/Provider/Blackboxai.py +0 -229
- webscout/Provider/C4ai.py +0 -432
- webscout/Provider/ChatGPTClone.py +0 -226
- webscout/Provider/ChatGPTES.py +0 -237
- webscout/Provider/ChatGPTGratis.py +0 -194
- webscout/Provider/Chatify.py +0 -175
- webscout/Provider/Cloudflare.py +0 -273
- webscout/Provider/DeepSeek.py +0 -196
- webscout/Provider/ElectronHub.py +0 -709
- webscout/Provider/ExaChat.py +0 -342
- webscout/Provider/Free2GPT.py +0 -241
- webscout/Provider/GPTWeb.py +0 -193
- webscout/Provider/Glider.py +0 -211
- webscout/Provider/HF_space/__init__.py +0 -0
- webscout/Provider/HF_space/qwen_qwen2.py +0 -206
- webscout/Provider/HuggingFaceChat.py +0 -462
- webscout/Provider/Hunyuan.py +0 -272
- webscout/Provider/LambdaChat.py +0 -392
- webscout/Provider/Llama.py +0 -200
- webscout/Provider/Llama3.py +0 -204
- webscout/Provider/Marcus.py +0 -148
- webscout/Provider/OLLAMA.py +0 -396
- webscout/Provider/OPENAI/c4ai.py +0 -367
- webscout/Provider/OPENAI/chatgptclone.py +0 -460
- webscout/Provider/OPENAI/exachat.py +0 -433
- webscout/Provider/OPENAI/freeaichat.py +0 -352
- webscout/Provider/OPENAI/opkfc.py +0 -488
- webscout/Provider/OPENAI/scirachat.py +0 -463
- webscout/Provider/OPENAI/standardinput.py +0 -425
- webscout/Provider/OPENAI/typegpt.py +0 -346
- webscout/Provider/OPENAI/uncovrAI.py +0 -455
- webscout/Provider/OPENAI/venice.py +0 -413
- webscout/Provider/OPENAI/yep.py +0 -327
- webscout/Provider/OpenGPT.py +0 -199
- webscout/Provider/Perplexitylabs.py +0 -415
- webscout/Provider/Phind.py +0 -535
- webscout/Provider/PizzaGPT.py +0 -198
- webscout/Provider/Reka.py +0 -214
- webscout/Provider/StandardInput.py +0 -278
- webscout/Provider/TTI/AiForce/__init__.py +0 -22
- webscout/Provider/TTI/AiForce/async_aiforce.py +0 -224
- webscout/Provider/TTI/AiForce/sync_aiforce.py +0 -245
- webscout/Provider/TTI/FreeAIPlayground/__init__.py +0 -9
- webscout/Provider/TTI/FreeAIPlayground/async_freeaiplayground.py +0 -181
- webscout/Provider/TTI/FreeAIPlayground/sync_freeaiplayground.py +0 -180
- webscout/Provider/TTI/ImgSys/__init__.py +0 -23
- webscout/Provider/TTI/ImgSys/async_imgsys.py +0 -202
- webscout/Provider/TTI/ImgSys/sync_imgsys.py +0 -195
- webscout/Provider/TTI/MagicStudio/__init__.py +0 -2
- webscout/Provider/TTI/MagicStudio/async_magicstudio.py +0 -111
- webscout/Provider/TTI/MagicStudio/sync_magicstudio.py +0 -109
- webscout/Provider/TTI/Nexra/__init__.py +0 -22
- webscout/Provider/TTI/Nexra/async_nexra.py +0 -286
- webscout/Provider/TTI/Nexra/sync_nexra.py +0 -258
- webscout/Provider/TTI/PollinationsAI/__init__.py +0 -23
- webscout/Provider/TTI/PollinationsAI/async_pollinations.py +0 -311
- webscout/Provider/TTI/PollinationsAI/sync_pollinations.py +0 -265
- webscout/Provider/TTI/aiarta/__init__.py +0 -2
- webscout/Provider/TTI/aiarta/async_aiarta.py +0 -482
- webscout/Provider/TTI/aiarta/sync_aiarta.py +0 -440
- webscout/Provider/TTI/artbit/__init__.py +0 -22
- webscout/Provider/TTI/artbit/async_artbit.py +0 -155
- webscout/Provider/TTI/artbit/sync_artbit.py +0 -148
- webscout/Provider/TTI/fastflux/__init__.py +0 -22
- webscout/Provider/TTI/fastflux/async_fastflux.py +0 -261
- webscout/Provider/TTI/fastflux/sync_fastflux.py +0 -252
- webscout/Provider/TTI/huggingface/__init__.py +0 -22
- webscout/Provider/TTI/huggingface/async_huggingface.py +0 -199
- webscout/Provider/TTI/huggingface/sync_huggingface.py +0 -195
- webscout/Provider/TTI/piclumen/__init__.py +0 -23
- webscout/Provider/TTI/piclumen/async_piclumen.py +0 -268
- webscout/Provider/TTI/piclumen/sync_piclumen.py +0 -233
- webscout/Provider/TTI/pixelmuse/__init__.py +0 -4
- webscout/Provider/TTI/pixelmuse/async_pixelmuse.py +0 -249
- webscout/Provider/TTI/pixelmuse/sync_pixelmuse.py +0 -182
- webscout/Provider/TTI/talkai/__init__.py +0 -4
- webscout/Provider/TTI/talkai/async_talkai.py +0 -229
- webscout/Provider/TTI/talkai/sync_talkai.py +0 -207
- webscout/Provider/TTS/gesserit.py +0 -127
- webscout/Provider/TeachAnything.py +0 -187
- webscout/Provider/Venice.py +0 -219
- webscout/Provider/VercelAI.py +0 -234
- webscout/Provider/WebSim.py +0 -228
- webscout/Provider/Writecream.py +0 -211
- webscout/Provider/WritingMate.py +0 -197
- webscout/Provider/aimathgpt.py +0 -189
- webscout/Provider/askmyai.py +0 -158
- webscout/Provider/asksteve.py +0 -203
- webscout/Provider/bagoodex.py +0 -145
- webscout/Provider/chatglm.py +0 -205
- webscout/Provider/copilot.py +0 -428
- webscout/Provider/freeaichat.py +0 -271
- webscout/Provider/gaurish.py +0 -244
- webscout/Provider/geminiprorealtime.py +0 -160
- webscout/Provider/granite.py +0 -187
- webscout/Provider/hermes.py +0 -219
- webscout/Provider/koala.py +0 -268
- webscout/Provider/labyrinth.py +0 -340
- webscout/Provider/lepton.py +0 -194
- webscout/Provider/llamatutor.py +0 -192
- webscout/Provider/multichat.py +0 -325
- webscout/Provider/promptrefine.py +0 -193
- webscout/Provider/scira_chat.py +0 -277
- webscout/Provider/scnet.py +0 -187
- webscout/Provider/talkai.py +0 -194
- webscout/Provider/tutorai.py +0 -252
- webscout/Provider/typegpt.py +0 -232
- webscout/Provider/uncovr.py +0 -312
- webscout/Provider/yep.py +0 -376
- webscout/litprinter/__init__.py +0 -59
- webscout/scout/core.py +0 -881
- webscout/tempid.py +0 -128
- webscout/webscout_search.py +0 -1346
- webscout/webscout_search_async.py +0 -877
- webscout/yep_search.py +0 -297
- webscout-8.2.2.dist-info/METADATA +0 -734
- webscout-8.2.2.dist-info/RECORD +0 -309
- webscout-8.2.2.dist-info/entry_points.txt +0 -5
- webscout-8.2.2.dist-info/top_level.txt +0 -3
- webstoken/__init__.py +0 -30
- webstoken/classifier.py +0 -189
- webstoken/keywords.py +0 -216
- webstoken/language.py +0 -128
- webstoken/ner.py +0 -164
- webstoken/normalizer.py +0 -35
- webstoken/processor.py +0 -77
- webstoken/sentiment.py +0 -206
- webstoken/stemmer.py +0 -73
- webstoken/tagger.py +0 -60
- webstoken/tokenizer.py +0 -158
- {webscout-8.2.2.dist-info → webscout-2026.1.19.dist-info/licenses}/LICENSE.md +0 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"""Command group handling for SwiftCLI."""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
|
|
7
|
+
from ..utils.formatting import format_error
|
|
8
|
+
from .context import Context
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from .cli import CLI
|
|
12
|
+
|
|
13
|
+
console = Console()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Group:
|
|
17
|
+
"""
|
|
18
|
+
Command group that can contain subcommands.
|
|
19
|
+
|
|
20
|
+
Groups allow organizing related commands together and support command
|
|
21
|
+
chaining for building command pipelines.
|
|
22
|
+
|
|
23
|
+
Attributes:
|
|
24
|
+
name: Group name
|
|
25
|
+
help: Group description
|
|
26
|
+
commands: Registered commands
|
|
27
|
+
parent: Parent CLI instance
|
|
28
|
+
chain: Enable command chaining
|
|
29
|
+
invoke_without_command: Allow invoking group without subcommand
|
|
30
|
+
|
|
31
|
+
Example:
|
|
32
|
+
@app.group()
|
|
33
|
+
def db():
|
|
34
|
+
'''Database commands'''
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
@db.command()
|
|
38
|
+
def migrate():
|
|
39
|
+
'''Run database migrations'''
|
|
40
|
+
print("Running migrations...")
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
name: str,
|
|
46
|
+
help: Optional[str] = None,
|
|
47
|
+
parent: Optional["CLI"] = None,
|
|
48
|
+
chain: bool = False,
|
|
49
|
+
invoke_without_command: bool = False,
|
|
50
|
+
):
|
|
51
|
+
"""
|
|
52
|
+
Initialize command group.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
name: Group name
|
|
56
|
+
help: Group description
|
|
57
|
+
parent: Parent CLI instance
|
|
58
|
+
chain: Enable command chaining
|
|
59
|
+
invoke_without_command: Allow invoking group without subcommand
|
|
60
|
+
"""
|
|
61
|
+
self.name = name
|
|
62
|
+
self.help = help
|
|
63
|
+
self.parent = parent
|
|
64
|
+
self.chain = chain
|
|
65
|
+
self.invoke_without_command = invoke_without_command
|
|
66
|
+
self.commands: Dict[str, Any] = {}
|
|
67
|
+
|
|
68
|
+
def command(
|
|
69
|
+
self,
|
|
70
|
+
name: Optional[str] = None,
|
|
71
|
+
help: Optional[str] = None,
|
|
72
|
+
aliases: Optional[List[str]] = None,
|
|
73
|
+
hidden: bool = False,
|
|
74
|
+
):
|
|
75
|
+
"""
|
|
76
|
+
Decorator to register a command in this group.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
name: Command name (defaults to function name)
|
|
80
|
+
help: Command help text
|
|
81
|
+
aliases: Alternative command names
|
|
82
|
+
hidden: Hide from help output
|
|
83
|
+
|
|
84
|
+
Example:
|
|
85
|
+
@group.command()
|
|
86
|
+
def status():
|
|
87
|
+
'''Show status'''
|
|
88
|
+
print("Status: OK")
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
def decorator(f):
|
|
92
|
+
cmd_name = name or f.__name__
|
|
93
|
+
self.commands[cmd_name] = {
|
|
94
|
+
"name": cmd_name,
|
|
95
|
+
"func": f,
|
|
96
|
+
"help": help or f.__doc__,
|
|
97
|
+
"aliases": aliases or [],
|
|
98
|
+
"hidden": hidden,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
# Register aliases
|
|
102
|
+
for alias in aliases or []:
|
|
103
|
+
self.commands[alias] = self.commands[cmd_name]
|
|
104
|
+
|
|
105
|
+
return f
|
|
106
|
+
|
|
107
|
+
return decorator
|
|
108
|
+
|
|
109
|
+
def group(self, name: Optional[str] = None, help: Optional[str] = None, **kwargs):
|
|
110
|
+
"""
|
|
111
|
+
Create a subgroup within this group.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
name: Subgroup name
|
|
115
|
+
help: Subgroup help text
|
|
116
|
+
**kwargs: Additional group options
|
|
117
|
+
|
|
118
|
+
Example:
|
|
119
|
+
@group.group()
|
|
120
|
+
def config():
|
|
121
|
+
'''Configuration commands'''
|
|
122
|
+
pass
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
def decorator(f):
|
|
126
|
+
subgroup = Group(
|
|
127
|
+
name=name or f.__name__, help=help or f.__doc__, parent=self.parent, **kwargs
|
|
128
|
+
)
|
|
129
|
+
self.commands[subgroup.name] = subgroup
|
|
130
|
+
return subgroup
|
|
131
|
+
|
|
132
|
+
return decorator
|
|
133
|
+
|
|
134
|
+
def run(self, args: List[str]) -> int:
|
|
135
|
+
"""
|
|
136
|
+
Run a command in this group.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
args: Command arguments
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
Exit code (0 for success, non-zero for error)
|
|
143
|
+
"""
|
|
144
|
+
try:
|
|
145
|
+
# Show help if no arguments or help requested
|
|
146
|
+
if not args or args[0] in ["-h", "--help"]:
|
|
147
|
+
self._print_help()
|
|
148
|
+
return 0
|
|
149
|
+
|
|
150
|
+
command_name = args[0]
|
|
151
|
+
command_args = args[1:]
|
|
152
|
+
|
|
153
|
+
# Check if command exists
|
|
154
|
+
if command_name not in self.commands:
|
|
155
|
+
format_error(f"Unknown command: {self.name} {command_name}")
|
|
156
|
+
self._print_help()
|
|
157
|
+
return 1
|
|
158
|
+
|
|
159
|
+
command = self.commands[command_name]
|
|
160
|
+
|
|
161
|
+
# Handle nested groups
|
|
162
|
+
if isinstance(command, Group):
|
|
163
|
+
return command.run(command_args)
|
|
164
|
+
|
|
165
|
+
# Create command context - parent is a CLI instance, never None at this point
|
|
166
|
+
# Context expects CLI type, and self.parent should be set when group is created by CLI
|
|
167
|
+
cli = self.parent
|
|
168
|
+
ctx = Context(
|
|
169
|
+
cli,
|
|
170
|
+
command=f"{self.name} {command_name}",
|
|
171
|
+
debug=getattr(self.parent, "debug", False) if self.parent else False,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
# Run command through plugin system
|
|
175
|
+
if self.parent and not self.parent.plugin_manager.before_command(
|
|
176
|
+
f"{self.name} {command_name}", command_args
|
|
177
|
+
):
|
|
178
|
+
return 1
|
|
179
|
+
|
|
180
|
+
try:
|
|
181
|
+
import asyncio
|
|
182
|
+
import inspect
|
|
183
|
+
|
|
184
|
+
func = command["func"]
|
|
185
|
+
params = self._parse_args(command, command_args)
|
|
186
|
+
|
|
187
|
+
# Inject context if function was decorated with pass_context
|
|
188
|
+
if getattr(func, "_pass_context", False):
|
|
189
|
+
call_args = (ctx,)
|
|
190
|
+
else:
|
|
191
|
+
call_args = ()
|
|
192
|
+
|
|
193
|
+
# If coroutine function, run it using asyncio
|
|
194
|
+
if inspect.iscoroutinefunction(func):
|
|
195
|
+
result = asyncio.run(func(*call_args, **params))
|
|
196
|
+
else:
|
|
197
|
+
result = func(*call_args, **params)
|
|
198
|
+
|
|
199
|
+
# If function returned a coroutine-like object
|
|
200
|
+
if not inspect.iscoroutine(result) and hasattr(result, "__await__"):
|
|
201
|
+
result = asyncio.run(result)
|
|
202
|
+
|
|
203
|
+
if self.parent:
|
|
204
|
+
self.parent.plugin_manager.after_command(
|
|
205
|
+
f"{self.name} {command_name}", command_args, result
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
# Handle command chaining
|
|
209
|
+
if self.chain and result is not None:
|
|
210
|
+
return result if isinstance(result, int) else 0
|
|
211
|
+
|
|
212
|
+
return 0
|
|
213
|
+
|
|
214
|
+
except Exception as e:
|
|
215
|
+
if self.parent:
|
|
216
|
+
self.parent.plugin_manager.on_error(f"{self.name} {command_name}", e)
|
|
217
|
+
if getattr(self.parent, "debug", False):
|
|
218
|
+
raise
|
|
219
|
+
format_error(str(e))
|
|
220
|
+
return 1
|
|
221
|
+
|
|
222
|
+
except Exception as e:
|
|
223
|
+
if getattr(self.parent, "debug", False):
|
|
224
|
+
raise
|
|
225
|
+
format_error(str(e))
|
|
226
|
+
return 1
|
|
227
|
+
|
|
228
|
+
def _parse_args(self, command: Dict[str, Any], args: List[str]) -> Dict[str, Any]:
|
|
229
|
+
"""Parse command arguments."""
|
|
230
|
+
# Use parent CLI's argument parser if available
|
|
231
|
+
if self.parent:
|
|
232
|
+
return self.parent._parse_args(command, args)
|
|
233
|
+
|
|
234
|
+
# Fallback to basic argument parsing
|
|
235
|
+
from ..utils.parsing import parse_args
|
|
236
|
+
|
|
237
|
+
return parse_args(args)
|
|
238
|
+
|
|
239
|
+
def _print_help(self) -> None:
|
|
240
|
+
"""Print group help message."""
|
|
241
|
+
console.print(f"\n[bold]{self.name}[/] - {self.help or ''}")
|
|
242
|
+
|
|
243
|
+
console.print("\n[bold]Commands:[/]")
|
|
244
|
+
printed = set()
|
|
245
|
+
for name, cmd in self.commands.items():
|
|
246
|
+
# cmd can be a Group or a dict mapping
|
|
247
|
+
if isinstance(cmd, Group):
|
|
248
|
+
primary = cmd.name
|
|
249
|
+
if primary in printed:
|
|
250
|
+
continue
|
|
251
|
+
printed.add(primary)
|
|
252
|
+
console.print(f" {primary} [group]")
|
|
253
|
+
if cmd.help:
|
|
254
|
+
console.print(f" {cmd.help}")
|
|
255
|
+
elif isinstance(cmd, dict):
|
|
256
|
+
primary = cmd.get("name", name)
|
|
257
|
+
if primary in printed:
|
|
258
|
+
continue
|
|
259
|
+
printed.add(primary)
|
|
260
|
+
if not cmd.get("hidden", False):
|
|
261
|
+
aliases = cmd.get("aliases", [])
|
|
262
|
+
alias_text = f" (aliases: {', '.join(aliases)})" if aliases else ""
|
|
263
|
+
console.print(f" {primary:20} {cmd['help'] or ''}{alias_text}")
|
|
264
|
+
|
|
265
|
+
console.print("\nUse -h or --help with any command for more info")
|
|
266
|
+
|
|
267
|
+
def __repr__(self) -> str:
|
|
268
|
+
return f"<Group name={self.name}>"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Decorators for SwiftCLI."""
|
|
2
|
+
|
|
3
|
+
from .command import argument, command, flag, group, pass_context
|
|
4
|
+
from .options import config_file, envvar, help_option, option, version_option
|
|
5
|
+
from .output import format_output, pager_output, panel_output, progress, table_output
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
# Command decorators
|
|
9
|
+
'command',
|
|
10
|
+
'group',
|
|
11
|
+
'argument',
|
|
12
|
+
'flag',
|
|
13
|
+
'pass_context',
|
|
14
|
+
|
|
15
|
+
# Option decorators
|
|
16
|
+
'option',
|
|
17
|
+
'envvar',
|
|
18
|
+
'config_file',
|
|
19
|
+
'version_option',
|
|
20
|
+
'help_option',
|
|
21
|
+
|
|
22
|
+
# Output decorators
|
|
23
|
+
'table_output',
|
|
24
|
+
'progress',
|
|
25
|
+
'panel_output',
|
|
26
|
+
'format_output',
|
|
27
|
+
'pager_output'
|
|
28
|
+
]
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"""Command decorators for SwiftCLI."""
|
|
2
|
+
|
|
3
|
+
from functools import wraps
|
|
4
|
+
from typing import Any, Callable, Dict, List, Optional
|
|
5
|
+
|
|
6
|
+
from ..core.context import Context
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def command(
|
|
10
|
+
name: Optional[str] = None,
|
|
11
|
+
help: Optional[str] = None,
|
|
12
|
+
aliases: Optional[List[str]] = None,
|
|
13
|
+
hidden: bool = False,
|
|
14
|
+
) -> Callable:
|
|
15
|
+
"""
|
|
16
|
+
Decorator to register a new command.
|
|
17
|
+
|
|
18
|
+
This decorator marks a function as a CLI command and provides metadata
|
|
19
|
+
about how command should be registered and displayed.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
name: Command name (defaults to function name)
|
|
23
|
+
help: Help text (defaults to function docstring)
|
|
24
|
+
aliases: Alternative names for command
|
|
25
|
+
hidden: Whether to hide from help output
|
|
26
|
+
|
|
27
|
+
Example:
|
|
28
|
+
@command(name="greet", help="Say hello")
|
|
29
|
+
def hello(name: str):
|
|
30
|
+
print(f"Hello {name}!")
|
|
31
|
+
|
|
32
|
+
@command(aliases=["hi", "hey"])
|
|
33
|
+
def hello(name: str):
|
|
34
|
+
'''Say hello to someone'''
|
|
35
|
+
print(f"Hello {name}!")
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def decorator(f: Callable) -> Callable:
|
|
39
|
+
f._command = { # type: ignore[attr-defined]
|
|
40
|
+
"name": name or getattr(f, '__name__', 'unknown'),
|
|
41
|
+
"help": help or f.__doc__,
|
|
42
|
+
"aliases": aliases or [],
|
|
43
|
+
"hidden": hidden,
|
|
44
|
+
}
|
|
45
|
+
return f
|
|
46
|
+
|
|
47
|
+
return decorator
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def group(
|
|
51
|
+
name: Optional[str] = None,
|
|
52
|
+
help: Optional[str] = None,
|
|
53
|
+
chain: bool = False,
|
|
54
|
+
invoke_without_command: bool = False,
|
|
55
|
+
) -> Callable:
|
|
56
|
+
"""
|
|
57
|
+
Decorator to create a command group.
|
|
58
|
+
|
|
59
|
+
Command groups can contain subcommands and optionally chain their results.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
name: Group name (defaults to function name)
|
|
63
|
+
help: Help text (defaults to function docstring)
|
|
64
|
+
chain: Whether to chain command results
|
|
65
|
+
invoke_without_command: Allow group to be invoked without subcommand
|
|
66
|
+
|
|
67
|
+
Example:
|
|
68
|
+
@group()
|
|
69
|
+
def db():
|
|
70
|
+
'''Database commands'''
|
|
71
|
+
pass
|
|
72
|
+
|
|
73
|
+
@db.command()
|
|
74
|
+
def migrate():
|
|
75
|
+
'''Run database migrations'''
|
|
76
|
+
print("Running migrations...")
|
|
77
|
+
|
|
78
|
+
@group(chain=True)
|
|
79
|
+
def process():
|
|
80
|
+
'''Process data'''
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
@process.command()
|
|
84
|
+
def validate():
|
|
85
|
+
'''Validate data'''
|
|
86
|
+
return {"valid": True}
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
def decorator(f: Callable) -> Callable:
|
|
90
|
+
f._group = { # type: ignore[attr-defined]
|
|
91
|
+
"name": name or getattr(f, '__name__', 'unknown'),
|
|
92
|
+
"help": help or f.__doc__,
|
|
93
|
+
"chain": chain,
|
|
94
|
+
"invoke_without_command": invoke_without_command,
|
|
95
|
+
}
|
|
96
|
+
return f
|
|
97
|
+
|
|
98
|
+
return decorator
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def pass_context(f: Callable) -> Callable:
|
|
102
|
+
"""
|
|
103
|
+
Decorator to pass CLI context to command.
|
|
104
|
+
|
|
105
|
+
This decorator injects current Context object as first argument
|
|
106
|
+
to the decorated command function.
|
|
107
|
+
|
|
108
|
+
Example:
|
|
109
|
+
@command()
|
|
110
|
+
@pass_context
|
|
111
|
+
def status(ctx):
|
|
112
|
+
'''Show application status'''
|
|
113
|
+
print(f"App: {ctx.cli.name}")
|
|
114
|
+
print(f"Debug: {ctx.debug}")
|
|
115
|
+
"""
|
|
116
|
+
f._pass_context = True # type: ignore[attr-defined]
|
|
117
|
+
return f
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def completion(func: Optional[Callable] = None) -> Callable:
|
|
121
|
+
"""
|
|
122
|
+
Decorator to provide shell completion for a command.
|
|
123
|
+
|
|
124
|
+
The decorated function should return a list of possible completions
|
|
125
|
+
based on current incomplete value.
|
|
126
|
+
|
|
127
|
+
Example:
|
|
128
|
+
@command()
|
|
129
|
+
@option("--service", type=str)
|
|
130
|
+
def restart(service: str):
|
|
131
|
+
'''Restart a service'''
|
|
132
|
+
print(f"Restarting {service}...")
|
|
133
|
+
|
|
134
|
+
@restart.completion()
|
|
135
|
+
def complete_service(ctx, incomplete):
|
|
136
|
+
services = ["nginx", "apache", "mysql"]
|
|
137
|
+
return [s for s in services if s.startswith(incomplete)]
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
def decorator(f: Callable) -> Callable:
|
|
141
|
+
@wraps(f)
|
|
142
|
+
def wrapper(ctx: Context, incomplete: str) -> List[str]:
|
|
143
|
+
try:
|
|
144
|
+
return f(ctx, incomplete)
|
|
145
|
+
except Exception:
|
|
146
|
+
return []
|
|
147
|
+
|
|
148
|
+
return wrapper
|
|
149
|
+
|
|
150
|
+
if func is None:
|
|
151
|
+
return decorator
|
|
152
|
+
return decorator(func)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def argument(
|
|
156
|
+
name: str,
|
|
157
|
+
type: Any = str,
|
|
158
|
+
required: bool = True,
|
|
159
|
+
help: Optional[str] = None,
|
|
160
|
+
default: Any = None,
|
|
161
|
+
validation: Optional[Dict[str, Any]] = None,
|
|
162
|
+
mutually_exclusive: Optional[List[str]] = None,
|
|
163
|
+
) -> Callable:
|
|
164
|
+
"""
|
|
165
|
+
Decorator to add a command argument.
|
|
166
|
+
|
|
167
|
+
Arguments are positional parameters that must be provided in order.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
name: Argument name
|
|
171
|
+
type: Expected type
|
|
172
|
+
required: Whether argument is required
|
|
173
|
+
help: Help text
|
|
174
|
+
default: Default value if not required
|
|
175
|
+
validation: Dictionary of validation rules (min_length, max_length, pattern, choices, etc.)
|
|
176
|
+
mutually_exclusive: List of argument names that are mutually exclusive with this argument
|
|
177
|
+
|
|
178
|
+
Example:
|
|
179
|
+
@command()
|
|
180
|
+
@argument("name", validation={'min_length': 2, 'max_length': 50})
|
|
181
|
+
@argument("count", type=int, default=1, validation={'min': 1, 'max': 100})
|
|
182
|
+
def greet(name: str, count: int):
|
|
183
|
+
'''Greet someone multiple times'''
|
|
184
|
+
for _ in range(count):
|
|
185
|
+
print(f"Hello {name}!")
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
def decorator(f: Callable) -> Callable:
|
|
189
|
+
if not hasattr(f, "_arguments"):
|
|
190
|
+
f._arguments = [] # type: ignore[attr-defined]
|
|
191
|
+
|
|
192
|
+
f._arguments.append( # type: ignore[attr-defined]
|
|
193
|
+
{
|
|
194
|
+
"name": name,
|
|
195
|
+
"type": type,
|
|
196
|
+
"required": required,
|
|
197
|
+
"help": help,
|
|
198
|
+
"default": default,
|
|
199
|
+
"validation": validation,
|
|
200
|
+
"mutually_exclusive": mutually_exclusive,
|
|
201
|
+
}
|
|
202
|
+
)
|
|
203
|
+
return f
|
|
204
|
+
|
|
205
|
+
return decorator
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def flag(name: str, help: Optional[str] = None, hidden: bool = False) -> Callable:
|
|
209
|
+
"""
|
|
210
|
+
Decorator to add a boolean flag option.
|
|
211
|
+
|
|
212
|
+
Flags are special options that don't take a value - they're either
|
|
213
|
+
present (True) or absent (False).
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
name: Flag name
|
|
217
|
+
help: Help text
|
|
218
|
+
hidden: Whether to hide from help output
|
|
219
|
+
|
|
220
|
+
Example:
|
|
221
|
+
@command()
|
|
222
|
+
@flag("--verbose", help="Enable verbose output")
|
|
223
|
+
def process(verbose: bool):
|
|
224
|
+
'''Process data'''
|
|
225
|
+
if verbose:
|
|
226
|
+
print("Verbose mode enabled")
|
|
227
|
+
"""
|
|
228
|
+
|
|
229
|
+
def decorator(f: Callable) -> Callable:
|
|
230
|
+
if not hasattr(f, "_options"):
|
|
231
|
+
f._options = [] # type: ignore[attr-defined]
|
|
232
|
+
|
|
233
|
+
f._options.append( # type: ignore[attr-defined]
|
|
234
|
+
{
|
|
235
|
+
"param_decls": [name],
|
|
236
|
+
"is_flag": True,
|
|
237
|
+
"help": help,
|
|
238
|
+
"hidden": hidden,
|
|
239
|
+
}
|
|
240
|
+
)
|
|
241
|
+
return f
|
|
242
|
+
|
|
243
|
+
return decorator
|