webscout 8.3.7__py3-none-any.whl → 2025.10.11__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.
Potentially problematic release.
This version of webscout might be problematic. Click here for more details.
- webscout/AIauto.py +250 -250
- webscout/AIbase.py +379 -379
- webscout/AIutel.py +60 -60
- webscout/Bard.py +1012 -1012
- webscout/Bing_search.py +417 -417
- webscout/DWEBS.py +529 -529
- webscout/Extra/Act.md +309 -309
- webscout/Extra/GitToolkit/__init__.py +10 -10
- webscout/Extra/GitToolkit/gitapi/README.md +110 -110
- webscout/Extra/GitToolkit/gitapi/__init__.py +11 -11
- webscout/Extra/GitToolkit/gitapi/repository.py +195 -195
- webscout/Extra/GitToolkit/gitapi/user.py +96 -96
- webscout/Extra/GitToolkit/gitapi/utils.py +61 -61
- webscout/Extra/YTToolkit/README.md +375 -375
- webscout/Extra/YTToolkit/YTdownloader.py +956 -956
- webscout/Extra/YTToolkit/__init__.py +2 -2
- webscout/Extra/YTToolkit/transcriber.py +475 -475
- webscout/Extra/YTToolkit/ytapi/README.md +44 -44
- webscout/Extra/YTToolkit/ytapi/__init__.py +6 -6
- webscout/Extra/YTToolkit/ytapi/channel.py +307 -307
- webscout/Extra/YTToolkit/ytapi/errors.py +13 -13
- webscout/Extra/YTToolkit/ytapi/extras.py +118 -118
- webscout/Extra/YTToolkit/ytapi/https.py +88 -88
- webscout/Extra/YTToolkit/ytapi/patterns.py +61 -61
- webscout/Extra/YTToolkit/ytapi/playlist.py +58 -58
- webscout/Extra/YTToolkit/ytapi/pool.py +7 -7
- webscout/Extra/YTToolkit/ytapi/query.py +39 -39
- webscout/Extra/YTToolkit/ytapi/stream.py +62 -62
- webscout/Extra/YTToolkit/ytapi/utils.py +62 -62
- webscout/Extra/YTToolkit/ytapi/video.py +232 -232
- webscout/Extra/autocoder/__init__.py +9 -9
- webscout/Extra/autocoder/autocoder.py +1105 -1105
- webscout/Extra/autocoder/autocoder_utiles.py +332 -332
- webscout/Extra/gguf.md +429 -429
- webscout/Extra/gguf.py +1213 -1213
- webscout/Extra/tempmail/README.md +487 -487
- webscout/Extra/tempmail/__init__.py +27 -27
- webscout/Extra/tempmail/async_utils.py +140 -140
- webscout/Extra/tempmail/base.py +160 -160
- webscout/Extra/tempmail/cli.py +186 -186
- webscout/Extra/tempmail/emailnator.py +84 -84
- webscout/Extra/tempmail/mail_tm.py +360 -360
- webscout/Extra/tempmail/temp_mail_io.py +291 -291
- webscout/Extra/weather.md +281 -281
- webscout/Extra/weather.py +193 -193
- webscout/Litlogger/README.md +10 -10
- webscout/Litlogger/__init__.py +15 -15
- webscout/Litlogger/formats.py +13 -13
- webscout/Litlogger/handlers.py +121 -121
- webscout/Litlogger/levels.py +13 -13
- webscout/Litlogger/logger.py +134 -134
- webscout/Provider/AISEARCH/Perplexity.py +332 -332
- webscout/Provider/AISEARCH/README.md +279 -279
- webscout/Provider/AISEARCH/__init__.py +16 -1
- webscout/Provider/AISEARCH/felo_search.py +206 -206
- webscout/Provider/AISEARCH/genspark_search.py +323 -323
- webscout/Provider/AISEARCH/hika_search.py +185 -185
- webscout/Provider/AISEARCH/iask_search.py +410 -410
- webscout/Provider/AISEARCH/monica_search.py +219 -219
- webscout/Provider/AISEARCH/scira_search.py +316 -316
- webscout/Provider/AISEARCH/stellar_search.py +177 -177
- webscout/Provider/AISEARCH/webpilotai_search.py +255 -255
- webscout/Provider/Aitopia.py +314 -314
- webscout/Provider/Apriel.py +306 -0
- webscout/Provider/ChatGPTClone.py +236 -236
- webscout/Provider/ChatSandbox.py +343 -343
- webscout/Provider/Cloudflare.py +324 -324
- webscout/Provider/Cohere.py +208 -208
- webscout/Provider/Deepinfra.py +370 -366
- webscout/Provider/ExaAI.py +260 -260
- webscout/Provider/ExaChat.py +308 -308
- webscout/Provider/Flowith.py +221 -221
- webscout/Provider/GMI.py +293 -0
- webscout/Provider/Gemini.py +164 -164
- webscout/Provider/GeminiProxy.py +167 -167
- webscout/Provider/GithubChat.py +371 -372
- webscout/Provider/Groq.py +800 -800
- webscout/Provider/HeckAI.py +383 -383
- webscout/Provider/Jadve.py +282 -282
- webscout/Provider/K2Think.py +307 -307
- webscout/Provider/Koboldai.py +205 -205
- webscout/Provider/LambdaChat.py +423 -423
- webscout/Provider/Nemotron.py +244 -244
- webscout/Provider/Netwrck.py +248 -248
- webscout/Provider/OLLAMA.py +395 -395
- webscout/Provider/OPENAI/Cloudflare.py +393 -393
- webscout/Provider/OPENAI/FalconH1.py +451 -451
- webscout/Provider/OPENAI/FreeGemini.py +296 -296
- webscout/Provider/OPENAI/K2Think.py +431 -431
- webscout/Provider/OPENAI/NEMOTRON.py +240 -240
- webscout/Provider/OPENAI/PI.py +427 -427
- webscout/Provider/OPENAI/README.md +959 -959
- webscout/Provider/OPENAI/TogetherAI.py +345 -345
- webscout/Provider/OPENAI/TwoAI.py +465 -465
- webscout/Provider/OPENAI/__init__.py +33 -18
- webscout/Provider/OPENAI/base.py +248 -248
- webscout/Provider/OPENAI/chatglm.py +528 -0
- webscout/Provider/OPENAI/chatgpt.py +592 -592
- webscout/Provider/OPENAI/chatgptclone.py +521 -521
- webscout/Provider/OPENAI/chatsandbox.py +202 -202
- webscout/Provider/OPENAI/deepinfra.py +318 -314
- webscout/Provider/OPENAI/e2b.py +1665 -1665
- webscout/Provider/OPENAI/exaai.py +420 -420
- webscout/Provider/OPENAI/exachat.py +452 -452
- webscout/Provider/OPENAI/friendli.py +232 -232
- webscout/Provider/OPENAI/{refact.py → gmi.py} +324 -274
- webscout/Provider/OPENAI/groq.py +364 -364
- webscout/Provider/OPENAI/heckai.py +314 -314
- webscout/Provider/OPENAI/llmchatco.py +337 -337
- webscout/Provider/OPENAI/netwrck.py +355 -355
- webscout/Provider/OPENAI/oivscode.py +290 -290
- webscout/Provider/OPENAI/opkfc.py +518 -518
- webscout/Provider/OPENAI/pydantic_imports.py +1 -1
- webscout/Provider/OPENAI/scirachat.py +535 -535
- webscout/Provider/OPENAI/sonus.py +308 -308
- webscout/Provider/OPENAI/standardinput.py +442 -442
- webscout/Provider/OPENAI/textpollinations.py +340 -340
- webscout/Provider/OPENAI/toolbaz.py +419 -416
- webscout/Provider/OPENAI/typefully.py +362 -362
- webscout/Provider/OPENAI/utils.py +295 -295
- webscout/Provider/OPENAI/venice.py +436 -436
- webscout/Provider/OPENAI/wisecat.py +387 -387
- webscout/Provider/OPENAI/writecream.py +166 -166
- webscout/Provider/OPENAI/x0gpt.py +378 -378
- webscout/Provider/OPENAI/yep.py +389 -389
- webscout/Provider/OpenGPT.py +230 -230
- webscout/Provider/Openai.py +243 -243
- webscout/Provider/PI.py +405 -405
- webscout/Provider/Perplexitylabs.py +430 -430
- webscout/Provider/QwenLM.py +272 -272
- webscout/Provider/STT/__init__.py +16 -1
- webscout/Provider/Sambanova.py +257 -257
- webscout/Provider/StandardInput.py +309 -309
- webscout/Provider/TTI/README.md +82 -82
- webscout/Provider/TTI/__init__.py +33 -18
- webscout/Provider/TTI/aiarta.py +413 -413
- webscout/Provider/TTI/base.py +136 -136
- webscout/Provider/TTI/bing.py +243 -243
- webscout/Provider/TTI/gpt1image.py +149 -149
- webscout/Provider/TTI/imagen.py +196 -196
- webscout/Provider/TTI/infip.py +211 -211
- webscout/Provider/TTI/magicstudio.py +232 -232
- webscout/Provider/TTI/monochat.py +219 -219
- webscout/Provider/TTI/piclumen.py +214 -214
- webscout/Provider/TTI/pixelmuse.py +232 -232
- webscout/Provider/TTI/pollinations.py +232 -232
- webscout/Provider/TTI/together.py +288 -288
- webscout/Provider/TTI/utils.py +12 -12
- webscout/Provider/TTI/venice.py +367 -367
- webscout/Provider/TTS/README.md +192 -192
- webscout/Provider/TTS/__init__.py +33 -18
- webscout/Provider/TTS/parler.py +110 -110
- webscout/Provider/TTS/streamElements.py +333 -333
- webscout/Provider/TTS/utils.py +280 -280
- webscout/Provider/TeachAnything.py +237 -237
- webscout/Provider/TextPollinationsAI.py +310 -310
- webscout/Provider/TogetherAI.py +356 -356
- webscout/Provider/TwoAI.py +312 -312
- webscout/Provider/TypliAI.py +311 -311
- webscout/Provider/UNFINISHED/ChatHub.py +208 -208
- webscout/Provider/UNFINISHED/ChutesAI.py +313 -313
- webscout/Provider/UNFINISHED/GizAI.py +294 -294
- webscout/Provider/UNFINISHED/Marcus.py +198 -198
- webscout/Provider/UNFINISHED/Qodo.py +477 -477
- webscout/Provider/UNFINISHED/VercelAIGateway.py +338 -338
- webscout/Provider/UNFINISHED/XenAI.py +324 -324
- webscout/Provider/UNFINISHED/Youchat.py +330 -330
- webscout/Provider/UNFINISHED/liner.py +334 -0
- webscout/Provider/UNFINISHED/liner_api_request.py +262 -262
- webscout/Provider/UNFINISHED/puterjs.py +634 -634
- webscout/Provider/UNFINISHED/samurai.py +223 -223
- webscout/Provider/UNFINISHED/test_lmarena.py +119 -119
- webscout/Provider/Venice.py +250 -250
- webscout/Provider/VercelAI.py +256 -256
- webscout/Provider/WiseCat.py +231 -231
- webscout/Provider/WrDoChat.py +366 -366
- webscout/Provider/__init__.py +33 -18
- webscout/Provider/ai4chat.py +174 -174
- webscout/Provider/akashgpt.py +331 -331
- webscout/Provider/cerebras.py +446 -446
- webscout/Provider/chatglm.py +394 -301
- webscout/Provider/cleeai.py +211 -211
- webscout/Provider/elmo.py +282 -282
- webscout/Provider/geminiapi.py +208 -208
- webscout/Provider/granite.py +261 -261
- webscout/Provider/hermes.py +263 -263
- webscout/Provider/julius.py +223 -223
- webscout/Provider/learnfastai.py +309 -309
- webscout/Provider/llama3mitril.py +214 -214
- webscout/Provider/llmchat.py +243 -243
- webscout/Provider/llmchatco.py +290 -290
- webscout/Provider/meta.py +801 -801
- webscout/Provider/oivscode.py +309 -309
- webscout/Provider/scira_chat.py +383 -383
- webscout/Provider/searchchat.py +292 -292
- webscout/Provider/sonus.py +258 -258
- webscout/Provider/toolbaz.py +370 -367
- webscout/Provider/turboseek.py +273 -273
- webscout/Provider/typefully.py +207 -207
- webscout/Provider/yep.py +372 -372
- webscout/__init__.py +30 -31
- webscout/__main__.py +5 -5
- webscout/auth/api_key_manager.py +189 -189
- webscout/auth/config.py +175 -175
- webscout/auth/models.py +185 -185
- webscout/auth/routes.py +664 -664
- webscout/auth/simple_logger.py +236 -236
- webscout/cli.py +523 -523
- webscout/conversation.py +438 -438
- webscout/exceptions.py +361 -361
- webscout/litagent/Readme.md +298 -298
- webscout/litagent/__init__.py +28 -28
- webscout/litagent/agent.py +581 -581
- webscout/litagent/constants.py +59 -59
- webscout/litprinter/__init__.py +58 -58
- webscout/models.py +181 -181
- webscout/optimizers.py +419 -419
- webscout/prompt_manager.py +288 -288
- webscout/sanitize.py +1078 -1078
- webscout/scout/README.md +401 -401
- webscout/scout/__init__.py +8 -8
- webscout/scout/core/__init__.py +6 -6
- webscout/scout/core/crawler.py +297 -297
- webscout/scout/core/scout.py +706 -706
- webscout/scout/core/search_result.py +95 -95
- webscout/scout/core/text_analyzer.py +62 -62
- webscout/scout/core/text_utils.py +277 -277
- webscout/scout/core/web_analyzer.py +51 -51
- webscout/scout/element.py +599 -599
- webscout/scout/parsers/__init__.py +69 -69
- webscout/scout/parsers/html5lib_parser.py +172 -172
- webscout/scout/parsers/html_parser.py +236 -236
- webscout/scout/parsers/lxml_parser.py +178 -178
- webscout/scout/utils.py +37 -37
- webscout/swiftcli/Readme.md +323 -323
- webscout/swiftcli/__init__.py +95 -95
- webscout/swiftcli/core/__init__.py +7 -7
- webscout/swiftcli/core/cli.py +308 -308
- webscout/swiftcli/core/context.py +104 -104
- webscout/swiftcli/core/group.py +241 -241
- webscout/swiftcli/decorators/__init__.py +28 -28
- webscout/swiftcli/decorators/command.py +221 -221
- webscout/swiftcli/decorators/options.py +220 -220
- webscout/swiftcli/decorators/output.py +302 -302
- webscout/swiftcli/exceptions.py +21 -21
- webscout/swiftcli/plugins/__init__.py +9 -9
- webscout/swiftcli/plugins/base.py +135 -135
- webscout/swiftcli/plugins/manager.py +269 -269
- webscout/swiftcli/utils/__init__.py +59 -59
- webscout/swiftcli/utils/formatting.py +252 -252
- webscout/swiftcli/utils/parsing.py +267 -267
- webscout/update_checker.py +117 -117
- webscout/version.py +1 -1
- webscout/webscout_search.py +1183 -1183
- webscout/webscout_search_async.py +649 -649
- webscout/yep_search.py +346 -346
- webscout/zeroart/README.md +89 -89
- webscout/zeroart/__init__.py +134 -134
- webscout/zeroart/base.py +66 -66
- webscout/zeroart/effects.py +100 -100
- webscout/zeroart/fonts.py +1238 -1238
- {webscout-8.3.7.dist-info → webscout-2025.10.11.dist-info}/METADATA +937 -937
- webscout-2025.10.11.dist-info/RECORD +300 -0
- webscout/Provider/AISEARCH/DeepFind.py +0 -254
- webscout/Provider/OPENAI/Qwen3.py +0 -303
- webscout/Provider/OPENAI/qodo.py +0 -630
- webscout/Provider/OPENAI/xenai.py +0 -514
- webscout/tempid.py +0 -134
- webscout-8.3.7.dist-info/RECORD +0 -301
- {webscout-8.3.7.dist-info → webscout-2025.10.11.dist-info}/WHEEL +0 -0
- {webscout-8.3.7.dist-info → webscout-2025.10.11.dist-info}/entry_points.txt +0 -0
- {webscout-8.3.7.dist-info → webscout-2025.10.11.dist-info}/licenses/LICENSE.md +0 -0
- {webscout-8.3.7.dist-info → webscout-2025.10.11.dist-info}/top_level.txt +0 -0
|
@@ -1,221 +1,221 @@
|
|
|
1
|
-
"""Command decorators for SwiftCLI."""
|
|
2
|
-
|
|
3
|
-
from functools import wraps
|
|
4
|
-
from typing import Any, Callable, Dict, List, Optional, Union
|
|
5
|
-
|
|
6
|
-
from ..core.context import Context
|
|
7
|
-
|
|
8
|
-
def command(
|
|
9
|
-
name: str = None,
|
|
10
|
-
help: str = None,
|
|
11
|
-
aliases: List[str] = None,
|
|
12
|
-
hidden: bool = False
|
|
13
|
-
) -> Callable:
|
|
14
|
-
"""
|
|
15
|
-
Decorator to register a new command.
|
|
16
|
-
|
|
17
|
-
This decorator marks a function as a CLI command and provides metadata
|
|
18
|
-
about how the command should be registered and displayed.
|
|
19
|
-
|
|
20
|
-
Args:
|
|
21
|
-
name: Command name (defaults to function name)
|
|
22
|
-
help: Help text (defaults to function docstring)
|
|
23
|
-
aliases: Alternative names for the command
|
|
24
|
-
hidden: Whether to hide from help output
|
|
25
|
-
|
|
26
|
-
Example:
|
|
27
|
-
@command(name="greet", help="Say hello")
|
|
28
|
-
def hello(name: str):
|
|
29
|
-
print(f"Hello {name}!")
|
|
30
|
-
|
|
31
|
-
@command(aliases=["hi", "hey"])
|
|
32
|
-
def hello(name: str):
|
|
33
|
-
'''Say hello to someone'''
|
|
34
|
-
print(f"Hello {name}!")
|
|
35
|
-
"""
|
|
36
|
-
def decorator(f: Callable) -> Callable:
|
|
37
|
-
f._command = {
|
|
38
|
-
'name': name or f.__name__,
|
|
39
|
-
'help': help or f.__doc__,
|
|
40
|
-
'aliases': aliases or [],
|
|
41
|
-
'hidden': hidden
|
|
42
|
-
}
|
|
43
|
-
return f
|
|
44
|
-
return decorator
|
|
45
|
-
|
|
46
|
-
def group(
|
|
47
|
-
name: str = None,
|
|
48
|
-
help: str = None,
|
|
49
|
-
chain: bool = False,
|
|
50
|
-
invoke_without_command: bool = False
|
|
51
|
-
) -> Callable:
|
|
52
|
-
"""
|
|
53
|
-
Decorator to create a command group.
|
|
54
|
-
|
|
55
|
-
Command groups can contain subcommands and optionally chain their results.
|
|
56
|
-
|
|
57
|
-
Args:
|
|
58
|
-
name: Group name (defaults to function name)
|
|
59
|
-
help: Help text (defaults to function docstring)
|
|
60
|
-
chain: Whether to chain command results
|
|
61
|
-
invoke_without_command: Allow group to be invoked without subcommand
|
|
62
|
-
|
|
63
|
-
Example:
|
|
64
|
-
@group()
|
|
65
|
-
def db():
|
|
66
|
-
'''Database commands'''
|
|
67
|
-
pass
|
|
68
|
-
|
|
69
|
-
@db.command()
|
|
70
|
-
def migrate():
|
|
71
|
-
'''Run database migrations'''
|
|
72
|
-
print("Running migrations...")
|
|
73
|
-
|
|
74
|
-
@group(chain=True)
|
|
75
|
-
def process():
|
|
76
|
-
'''Process data'''
|
|
77
|
-
pass
|
|
78
|
-
|
|
79
|
-
@process.command()
|
|
80
|
-
def validate():
|
|
81
|
-
'''Validate data'''
|
|
82
|
-
return {"valid": True}
|
|
83
|
-
"""
|
|
84
|
-
def decorator(f: Callable) -> Callable:
|
|
85
|
-
f._group = {
|
|
86
|
-
'name': name or f.__name__,
|
|
87
|
-
'help': help or f.__doc__,
|
|
88
|
-
'chain': chain,
|
|
89
|
-
'invoke_without_command': invoke_without_command
|
|
90
|
-
}
|
|
91
|
-
return f
|
|
92
|
-
return decorator
|
|
93
|
-
|
|
94
|
-
def pass_context(f: Callable) -> Callable:
|
|
95
|
-
"""
|
|
96
|
-
Decorator to pass CLI context to command.
|
|
97
|
-
|
|
98
|
-
This decorator injects the current Context object as the first argument
|
|
99
|
-
to the decorated command function.
|
|
100
|
-
|
|
101
|
-
Example:
|
|
102
|
-
@command()
|
|
103
|
-
@pass_context
|
|
104
|
-
def status(ctx):
|
|
105
|
-
'''Show application status'''
|
|
106
|
-
print(f"App: {ctx.cli.name}")
|
|
107
|
-
print(f"Debug: {ctx.debug}")
|
|
108
|
-
"""
|
|
109
|
-
f._pass_context = True
|
|
110
|
-
return f
|
|
111
|
-
|
|
112
|
-
def completion(func: Optional[Callable] = None) -> Callable:
|
|
113
|
-
"""
|
|
114
|
-
Decorator to provide shell completion for a command.
|
|
115
|
-
|
|
116
|
-
The decorated function should return a list of possible completions
|
|
117
|
-
based on the current incomplete value.
|
|
118
|
-
|
|
119
|
-
Example:
|
|
120
|
-
@command()
|
|
121
|
-
@option("--service", type=str)
|
|
122
|
-
def restart(service: str):
|
|
123
|
-
'''Restart a service'''
|
|
124
|
-
print(f"Restarting {service}...")
|
|
125
|
-
|
|
126
|
-
@restart.completion()
|
|
127
|
-
def complete_service(ctx, incomplete):
|
|
128
|
-
services = ["nginx", "apache", "mysql"]
|
|
129
|
-
return [s for s in services if s.startswith(incomplete)]
|
|
130
|
-
"""
|
|
131
|
-
def decorator(f: Callable) -> Callable:
|
|
132
|
-
@wraps(f)
|
|
133
|
-
def wrapper(ctx: Context, incomplete: str) -> List[str]:
|
|
134
|
-
try:
|
|
135
|
-
return f(ctx, incomplete)
|
|
136
|
-
except Exception:
|
|
137
|
-
return []
|
|
138
|
-
return wrapper
|
|
139
|
-
|
|
140
|
-
if func is None:
|
|
141
|
-
return decorator
|
|
142
|
-
return decorator(func)
|
|
143
|
-
|
|
144
|
-
def argument(
|
|
145
|
-
name: str,
|
|
146
|
-
type: Any = str,
|
|
147
|
-
required: bool = True,
|
|
148
|
-
help: str = None,
|
|
149
|
-
default: Any = None
|
|
150
|
-
) -> Callable:
|
|
151
|
-
"""
|
|
152
|
-
Decorator to add a command argument.
|
|
153
|
-
|
|
154
|
-
Arguments are positional parameters that must be provided in order.
|
|
155
|
-
|
|
156
|
-
Args:
|
|
157
|
-
name: Argument name
|
|
158
|
-
type: Expected type
|
|
159
|
-
required: Whether argument is required
|
|
160
|
-
help: Help text
|
|
161
|
-
default: Default value if not required
|
|
162
|
-
|
|
163
|
-
Example:
|
|
164
|
-
@command()
|
|
165
|
-
@argument("name")
|
|
166
|
-
@argument("count", type=int, default=1)
|
|
167
|
-
def greet(name: str, count: int):
|
|
168
|
-
'''Greet someone multiple times'''
|
|
169
|
-
for _ in range(count):
|
|
170
|
-
print(f"Hello {name}!")
|
|
171
|
-
"""
|
|
172
|
-
def decorator(f: Callable) -> Callable:
|
|
173
|
-
if not hasattr(f, '_arguments'):
|
|
174
|
-
f._arguments = []
|
|
175
|
-
|
|
176
|
-
f._arguments.append({
|
|
177
|
-
'name': name,
|
|
178
|
-
'type': type,
|
|
179
|
-
'required': required,
|
|
180
|
-
'help': help,
|
|
181
|
-
'default': default
|
|
182
|
-
})
|
|
183
|
-
return f
|
|
184
|
-
return decorator
|
|
185
|
-
|
|
186
|
-
def flag(
|
|
187
|
-
name: str,
|
|
188
|
-
help: str = None,
|
|
189
|
-
hidden: bool = False
|
|
190
|
-
) -> Callable:
|
|
191
|
-
"""
|
|
192
|
-
Decorator to add a boolean flag option.
|
|
193
|
-
|
|
194
|
-
Flags are special options that don't take a value - they're either
|
|
195
|
-
present (True) or absent (False).
|
|
196
|
-
|
|
197
|
-
Args:
|
|
198
|
-
name: Flag name
|
|
199
|
-
help: Help text
|
|
200
|
-
hidden: Whether to hide from help output
|
|
201
|
-
|
|
202
|
-
Example:
|
|
203
|
-
@command()
|
|
204
|
-
@flag("--verbose", help="Enable verbose output")
|
|
205
|
-
def process(verbose: bool):
|
|
206
|
-
'''Process data'''
|
|
207
|
-
if verbose:
|
|
208
|
-
print("Verbose mode enabled")
|
|
209
|
-
"""
|
|
210
|
-
def decorator(f: Callable) -> Callable:
|
|
211
|
-
if not hasattr(f, '_options'):
|
|
212
|
-
f._options = []
|
|
213
|
-
|
|
214
|
-
f._options.append({
|
|
215
|
-
'param_decls': [name],
|
|
216
|
-
'is_flag': True,
|
|
217
|
-
'help': help,
|
|
218
|
-
'hidden': hidden
|
|
219
|
-
})
|
|
220
|
-
return f
|
|
221
|
-
return decorator
|
|
1
|
+
"""Command decorators for SwiftCLI."""
|
|
2
|
+
|
|
3
|
+
from functools import wraps
|
|
4
|
+
from typing import Any, Callable, Dict, List, Optional, Union
|
|
5
|
+
|
|
6
|
+
from ..core.context import Context
|
|
7
|
+
|
|
8
|
+
def command(
|
|
9
|
+
name: str = None,
|
|
10
|
+
help: str = None,
|
|
11
|
+
aliases: List[str] = None,
|
|
12
|
+
hidden: bool = False
|
|
13
|
+
) -> Callable:
|
|
14
|
+
"""
|
|
15
|
+
Decorator to register a new command.
|
|
16
|
+
|
|
17
|
+
This decorator marks a function as a CLI command and provides metadata
|
|
18
|
+
about how the command should be registered and displayed.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
name: Command name (defaults to function name)
|
|
22
|
+
help: Help text (defaults to function docstring)
|
|
23
|
+
aliases: Alternative names for the command
|
|
24
|
+
hidden: Whether to hide from help output
|
|
25
|
+
|
|
26
|
+
Example:
|
|
27
|
+
@command(name="greet", help="Say hello")
|
|
28
|
+
def hello(name: str):
|
|
29
|
+
print(f"Hello {name}!")
|
|
30
|
+
|
|
31
|
+
@command(aliases=["hi", "hey"])
|
|
32
|
+
def hello(name: str):
|
|
33
|
+
'''Say hello to someone'''
|
|
34
|
+
print(f"Hello {name}!")
|
|
35
|
+
"""
|
|
36
|
+
def decorator(f: Callable) -> Callable:
|
|
37
|
+
f._command = {
|
|
38
|
+
'name': name or f.__name__,
|
|
39
|
+
'help': help or f.__doc__,
|
|
40
|
+
'aliases': aliases or [],
|
|
41
|
+
'hidden': hidden
|
|
42
|
+
}
|
|
43
|
+
return f
|
|
44
|
+
return decorator
|
|
45
|
+
|
|
46
|
+
def group(
|
|
47
|
+
name: str = None,
|
|
48
|
+
help: str = None,
|
|
49
|
+
chain: bool = False,
|
|
50
|
+
invoke_without_command: bool = False
|
|
51
|
+
) -> Callable:
|
|
52
|
+
"""
|
|
53
|
+
Decorator to create a command group.
|
|
54
|
+
|
|
55
|
+
Command groups can contain subcommands and optionally chain their results.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
name: Group name (defaults to function name)
|
|
59
|
+
help: Help text (defaults to function docstring)
|
|
60
|
+
chain: Whether to chain command results
|
|
61
|
+
invoke_without_command: Allow group to be invoked without subcommand
|
|
62
|
+
|
|
63
|
+
Example:
|
|
64
|
+
@group()
|
|
65
|
+
def db():
|
|
66
|
+
'''Database commands'''
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
@db.command()
|
|
70
|
+
def migrate():
|
|
71
|
+
'''Run database migrations'''
|
|
72
|
+
print("Running migrations...")
|
|
73
|
+
|
|
74
|
+
@group(chain=True)
|
|
75
|
+
def process():
|
|
76
|
+
'''Process data'''
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
@process.command()
|
|
80
|
+
def validate():
|
|
81
|
+
'''Validate data'''
|
|
82
|
+
return {"valid": True}
|
|
83
|
+
"""
|
|
84
|
+
def decorator(f: Callable) -> Callable:
|
|
85
|
+
f._group = {
|
|
86
|
+
'name': name or f.__name__,
|
|
87
|
+
'help': help or f.__doc__,
|
|
88
|
+
'chain': chain,
|
|
89
|
+
'invoke_without_command': invoke_without_command
|
|
90
|
+
}
|
|
91
|
+
return f
|
|
92
|
+
return decorator
|
|
93
|
+
|
|
94
|
+
def pass_context(f: Callable) -> Callable:
|
|
95
|
+
"""
|
|
96
|
+
Decorator to pass CLI context to command.
|
|
97
|
+
|
|
98
|
+
This decorator injects the current Context object as the first argument
|
|
99
|
+
to the decorated command function.
|
|
100
|
+
|
|
101
|
+
Example:
|
|
102
|
+
@command()
|
|
103
|
+
@pass_context
|
|
104
|
+
def status(ctx):
|
|
105
|
+
'''Show application status'''
|
|
106
|
+
print(f"App: {ctx.cli.name}")
|
|
107
|
+
print(f"Debug: {ctx.debug}")
|
|
108
|
+
"""
|
|
109
|
+
f._pass_context = True
|
|
110
|
+
return f
|
|
111
|
+
|
|
112
|
+
def completion(func: Optional[Callable] = None) -> Callable:
|
|
113
|
+
"""
|
|
114
|
+
Decorator to provide shell completion for a command.
|
|
115
|
+
|
|
116
|
+
The decorated function should return a list of possible completions
|
|
117
|
+
based on the current incomplete value.
|
|
118
|
+
|
|
119
|
+
Example:
|
|
120
|
+
@command()
|
|
121
|
+
@option("--service", type=str)
|
|
122
|
+
def restart(service: str):
|
|
123
|
+
'''Restart a service'''
|
|
124
|
+
print(f"Restarting {service}...")
|
|
125
|
+
|
|
126
|
+
@restart.completion()
|
|
127
|
+
def complete_service(ctx, incomplete):
|
|
128
|
+
services = ["nginx", "apache", "mysql"]
|
|
129
|
+
return [s for s in services if s.startswith(incomplete)]
|
|
130
|
+
"""
|
|
131
|
+
def decorator(f: Callable) -> Callable:
|
|
132
|
+
@wraps(f)
|
|
133
|
+
def wrapper(ctx: Context, incomplete: str) -> List[str]:
|
|
134
|
+
try:
|
|
135
|
+
return f(ctx, incomplete)
|
|
136
|
+
except Exception:
|
|
137
|
+
return []
|
|
138
|
+
return wrapper
|
|
139
|
+
|
|
140
|
+
if func is None:
|
|
141
|
+
return decorator
|
|
142
|
+
return decorator(func)
|
|
143
|
+
|
|
144
|
+
def argument(
|
|
145
|
+
name: str,
|
|
146
|
+
type: Any = str,
|
|
147
|
+
required: bool = True,
|
|
148
|
+
help: str = None,
|
|
149
|
+
default: Any = None
|
|
150
|
+
) -> Callable:
|
|
151
|
+
"""
|
|
152
|
+
Decorator to add a command argument.
|
|
153
|
+
|
|
154
|
+
Arguments are positional parameters that must be provided in order.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
name: Argument name
|
|
158
|
+
type: Expected type
|
|
159
|
+
required: Whether argument is required
|
|
160
|
+
help: Help text
|
|
161
|
+
default: Default value if not required
|
|
162
|
+
|
|
163
|
+
Example:
|
|
164
|
+
@command()
|
|
165
|
+
@argument("name")
|
|
166
|
+
@argument("count", type=int, default=1)
|
|
167
|
+
def greet(name: str, count: int):
|
|
168
|
+
'''Greet someone multiple times'''
|
|
169
|
+
for _ in range(count):
|
|
170
|
+
print(f"Hello {name}!")
|
|
171
|
+
"""
|
|
172
|
+
def decorator(f: Callable) -> Callable:
|
|
173
|
+
if not hasattr(f, '_arguments'):
|
|
174
|
+
f._arguments = []
|
|
175
|
+
|
|
176
|
+
f._arguments.append({
|
|
177
|
+
'name': name,
|
|
178
|
+
'type': type,
|
|
179
|
+
'required': required,
|
|
180
|
+
'help': help,
|
|
181
|
+
'default': default
|
|
182
|
+
})
|
|
183
|
+
return f
|
|
184
|
+
return decorator
|
|
185
|
+
|
|
186
|
+
def flag(
|
|
187
|
+
name: str,
|
|
188
|
+
help: str = None,
|
|
189
|
+
hidden: bool = False
|
|
190
|
+
) -> Callable:
|
|
191
|
+
"""
|
|
192
|
+
Decorator to add a boolean flag option.
|
|
193
|
+
|
|
194
|
+
Flags are special options that don't take a value - they're either
|
|
195
|
+
present (True) or absent (False).
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
name: Flag name
|
|
199
|
+
help: Help text
|
|
200
|
+
hidden: Whether to hide from help output
|
|
201
|
+
|
|
202
|
+
Example:
|
|
203
|
+
@command()
|
|
204
|
+
@flag("--verbose", help="Enable verbose output")
|
|
205
|
+
def process(verbose: bool):
|
|
206
|
+
'''Process data'''
|
|
207
|
+
if verbose:
|
|
208
|
+
print("Verbose mode enabled")
|
|
209
|
+
"""
|
|
210
|
+
def decorator(f: Callable) -> Callable:
|
|
211
|
+
if not hasattr(f, '_options'):
|
|
212
|
+
f._options = []
|
|
213
|
+
|
|
214
|
+
f._options.append({
|
|
215
|
+
'param_decls': [name],
|
|
216
|
+
'is_flag': True,
|
|
217
|
+
'help': help,
|
|
218
|
+
'hidden': hidden
|
|
219
|
+
})
|
|
220
|
+
return f
|
|
221
|
+
return decorator
|