Skip to content

Commit 08ec182

Browse files
authored
Merge pull request #95 from yassun7010/add_delegate_command
Add delegate command
2 parents 951b1af + 8bd893a commit 08ec182

20 files changed

+1023
-486
lines changed

cmdcomp/v2/command/__init__.py

Lines changed: 4 additions & 311 deletions
Original file line numberDiff line numberDiff line change
@@ -1,312 +1,5 @@
1-
from abc import ABCMeta, abstractmethod
2-
from functools import cached_property
3-
from typing import Annotated, Literal, OrderedDict, TypeAlias
1+
from .delegate_command import V2DelegateCommand
2+
from .positional_arguments_command import V2PositionalArgumentsCommand
3+
from .subcommands_command import V2SubcommandsCommand
44

5-
from pydantic import ConfigDict, Field
6-
from typing_extensions import override
7-
8-
from cmdcomp.model import Model
9-
from cmdcomp.v2.command.argument.flag_argument import V2FlagArgument
10-
from cmdcomp.v2.command.argument.select_argument import V2SelectArgument
11-
from cmdcomp.v2.mixin.has_alias import HasAlias
12-
13-
from .argument import V2Argument
14-
15-
Position: TypeAlias = Annotated[int, Field(ge=1)]
16-
Keyword = Annotated[str, Field(pattern=r"^--?[a-zA-Z0-9_-]+$")]
17-
SubcommandName: TypeAlias = str
18-
_InputArgument = str | list[str] | V2Argument
19-
20-
21-
class _V2BaseCommand(HasAlias, Model, metaclass=ABCMeta):
22-
model_config = ConfigDict(arbitrary_types_allowed=True)
23-
24-
description: Annotated[
25-
str | None,
26-
Field(title="description of the command."),
27-
] = None
28-
29-
alias: Annotated[
30-
str | list[str] | None,
31-
Field(title="alias of the command."),
32-
] = None
33-
34-
@cached_property
35-
def subcommand_names_with_alias(self) -> list[SubcommandName]:
36-
result: list[SubcommandName] = []
37-
for subcommand_name, subcommand in self.subcommands.items():
38-
result.append(subcommand_name)
39-
result.extend(subcommand.aliases)
40-
41-
return result
42-
43-
@cached_property
44-
def keyword_names_with_alias(self) -> list[Keyword]:
45-
result: list[Keyword] = []
46-
for keyword, argument in self.keyword_arguments.items():
47-
result.append(keyword)
48-
result.extend(argument.aliases)
49-
50-
return result
51-
52-
@property
53-
@abstractmethod
54-
def subcommands(self) -> OrderedDict[SubcommandName, "V2Command"]:
55-
...
56-
57-
@property
58-
@abstractmethod
59-
def positional_arguments(self) -> OrderedDict[Position, V2Argument]:
60-
...
61-
62-
@property
63-
@abstractmethod
64-
def positional_wildcard_argument(self) -> V2Argument | None:
65-
...
66-
67-
@property
68-
@abstractmethod
69-
def keyword_arguments(self) -> OrderedDict[Keyword, V2Argument]:
70-
...
71-
72-
@property
73-
@abstractmethod
74-
def has_subcommands(self) -> bool:
75-
...
76-
77-
@property
78-
@abstractmethod
79-
def has_positional_arguments(self) -> bool:
80-
...
81-
82-
@property
83-
@abstractmethod
84-
def has_positional_wildcard_argument(self) -> bool:
85-
...
86-
87-
@property
88-
@abstractmethod
89-
def has_keyword_arguments(self) -> bool:
90-
...
91-
92-
93-
class _V2EmptyCommand(_V2BaseCommand):
94-
@property
95-
@override
96-
def subcommands(self) -> OrderedDict[SubcommandName, "V2Command"]:
97-
return OrderedDict()
98-
99-
@property
100-
@override
101-
def positional_arguments(self) -> OrderedDict[Position, V2Argument]:
102-
return OrderedDict()
103-
104-
@property
105-
@override
106-
def positional_wildcard_argument(self) -> V2Argument | None:
107-
return None
108-
109-
@property
110-
@override
111-
def keyword_arguments(self) -> OrderedDict[Keyword, V2Argument]:
112-
return OrderedDict()
113-
114-
@property
115-
@override
116-
def has_subcommands(self) -> bool:
117-
return False
118-
119-
@property
120-
@override
121-
def has_positional_arguments(self) -> bool:
122-
return False
123-
124-
@property
125-
@override
126-
def has_positional_wildcard_argument(self) -> bool:
127-
return False
128-
129-
@property
130-
@override
131-
def has_keyword_arguments(self) -> bool:
132-
return False
133-
134-
135-
class V2PoristionalArgumentsCommand(_V2BaseCommand):
136-
arguments: Annotated[
137-
OrderedDict[Position | Literal["*"] | Keyword, _InputArgument | None],
138-
Field(
139-
title="arguments of the command.",
140-
description=(
141-
"argment key allow "
142-
"positional integer (like 1, 2), "
143-
'keyword string (like "--f", "-f"), '
144-
'wildcard string ("*").'
145-
),
146-
),
147-
]
148-
149-
@property
150-
@override
151-
def subcommands(self) -> OrderedDict[SubcommandName, "V2Command"]:
152-
return OrderedDict()
153-
154-
@cached_property
155-
@override
156-
def positional_arguments(self) -> OrderedDict[Position, V2Argument]:
157-
return OrderedDict(
158-
[
159-
(k, _convert_argument(v))
160-
for k, v in self.arguments.items()
161-
if isinstance(k, int)
162-
]
163-
)
164-
165-
@cached_property
166-
@override
167-
def positional_wildcard_argument(self) -> V2Argument | None:
168-
if "*" in self.arguments:
169-
return _convert_argument(self.arguments["*"])
170-
else:
171-
return None
172-
173-
@cached_property
174-
@override
175-
def keyword_arguments(self) -> OrderedDict[Keyword, V2Argument]:
176-
return OrderedDict(
177-
[
178-
(k, _convert_argument(v))
179-
for k, v in self.arguments.items()
180-
if isinstance(k, str) and k != "*"
181-
]
182-
)
183-
184-
@property
185-
@override
186-
def has_subcommands(self) -> bool:
187-
return False
188-
189-
@property
190-
@override
191-
def has_positional_arguments(self) -> bool:
192-
return len(self.positional_arguments) != 0
193-
194-
@property
195-
@override
196-
def has_positional_wildcard_argument(self) -> bool:
197-
return self.positional_wildcard_argument is not None
198-
199-
@property
200-
@override
201-
def has_keyword_arguments(self) -> bool:
202-
return len(self.keyword_arguments) != 0
203-
204-
205-
class V2SubcommandsCommand(_V2BaseCommand):
206-
arguments: OrderedDict[Keyword, _InputArgument | None] = Field(
207-
title="arguments of the command.",
208-
description='argment key allow keyword string (like "--f", "-f") only.',
209-
default_factory=OrderedDict,
210-
)
211-
212-
raw_subcommands: OrderedDict[SubcommandName, "V2Command | None"] = Field(
213-
title="subcommands of the command.",
214-
alias="subcommands",
215-
default_factory=OrderedDict,
216-
)
217-
218-
@property
219-
@override
220-
def positional_arguments(self) -> OrderedDict[Position, V2Argument]:
221-
return OrderedDict()
222-
223-
@property
224-
@override
225-
def positional_wildcard_argument(self) -> V2Argument | None:
226-
return None
227-
228-
@cached_property
229-
@override
230-
def keyword_arguments(self) -> OrderedDict[Keyword, V2Argument]:
231-
return OrderedDict(
232-
[
233-
(k, _convert_argument(v))
234-
for k, v in self.arguments.items()
235-
if isinstance(k, str)
236-
]
237-
)
238-
239-
@cached_property
240-
@override
241-
def subcommands(self) -> OrderedDict[SubcommandName, "V2Command"]:
242-
return OrderedDict(
243-
[
244-
(
245-
name,
246-
V2SubcommandsCommand() if subcommand is None else subcommand,
247-
)
248-
for name, subcommand in self.raw_subcommands.items()
249-
]
250-
)
251-
252-
@property
253-
@override
254-
def has_subcommands(self) -> bool:
255-
return len(self.subcommands) != 0
256-
257-
@property
258-
@override
259-
def has_positional_arguments(self) -> bool:
260-
return False
261-
262-
@property
263-
@override
264-
def has_positional_wildcard_argument(self) -> bool:
265-
return self.positional_wildcard_argument is not None
266-
267-
@property
268-
@override
269-
def has_keyword_arguments(self) -> bool:
270-
return len(self.keyword_arguments) != 0
271-
272-
273-
class V2RelayCommand(_V2EmptyCommand):
274-
"""relay completion of other command."""
275-
276-
type: Annotated[
277-
Literal["relay"],
278-
Field(title="relay completion of other command."),
279-
]
280-
281-
description: Annotated[
282-
str | None,
283-
Field(title="description of the argument."),
284-
] = None
285-
286-
alias: Annotated[
287-
str | list[str] | None,
288-
Field(title="alias of the argument."),
289-
] = None
290-
291-
target: Annotated[str, Field(title="relay target.")]
292-
293-
294-
V2Command = V2PoristionalArgumentsCommand | V2SubcommandsCommand | V2RelayCommand
295-
296-
297-
def _convert_argument(value: _InputArgument | None) -> V2Argument:
298-
match value:
299-
case str():
300-
return V2SelectArgument(type="select", raw_options=[value])
301-
302-
case list():
303-
return V2SelectArgument(
304-
type="select",
305-
raw_options=[v for v in value],
306-
)
307-
308-
case None:
309-
return V2FlagArgument(type="flag")
310-
311-
case _:
312-
return value
5+
V2Command = V2PositionalArgumentsCommand | V2SubcommandsCommand | V2DelegateCommand

0 commit comments

Comments
 (0)