Skip to content

Commit e03ce6f

Browse files
trag1cjohnslavik
andauthored
Miscellaneous improvements throughout the codebase (#365)
Co-authored-by: bswck <[email protected]>
1 parent 95452e5 commit e03ce6f

34 files changed

+280
-364
lines changed

src/cleo/_utils.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,23 @@ def find_similar_names(name: str, names: list[str]) -> list[str]:
5959
distance = Levenshtein.distance(name, actual_name)
6060

6161
is_similar = distance <= len(name) / 3
62-
is_sub_string = actual_name.find(name) != -1
62+
substring_index = actual_name.find(name)
63+
is_substring = substring_index != -1
6364

64-
if is_similar or is_sub_string:
65+
if is_similar or is_substring:
6566
distance_by_name[actual_name] = (
6667
distance,
67-
actual_name.find(name) if is_sub_string else float("inf"),
68+
substring_index if is_substring else float("inf"),
6869
)
6970

7071
# Only keep results with a distance below the threshold
7172
distance_by_name = {
72-
k: v for k, v in distance_by_name.items() if v[0] < 2 * threshold
73+
key: value
74+
for key, value in distance_by_name.items()
75+
if value[0] < 2 * threshold
7376
}
7477
# Display results with shortest distance first
75-
return sorted(distance_by_name, key=lambda x: distance_by_name[x])
78+
return sorted(distance_by_name, key=lambda key: distance_by_name[key])
7679

7780

7881
@dataclass
@@ -101,7 +104,7 @@ def apply(self, secs: float) -> str:
101104

102105

103106
def format_time(secs: float) -> str:
104-
format = next(
107+
time_format = next(
105108
(fmt for fmt in _TIME_FORMATS if secs < fmt.threshold), _TIME_FORMATS[-1]
106109
)
107-
return format.apply(secs)
110+
return time_format.apply(secs)

src/cleo/application.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ def _run(self, io: IO) -> int:
420420
break
421421

422422
if index is not None:
423-
del argv[index + 1 : index + 1 + (len(name.split(" ")) - 1)]
423+
del argv[index + 1 : index + 1 + name.count(" ")]
424424

425425
stream = io.input.stream
426426
interactive = io.input.is_interactive()
@@ -614,11 +614,7 @@ def _get_command_name(self, io: IO) -> str | None:
614614

615615
def extract_namespace(self, name: str, limit: int | None = None) -> str:
616616
parts = name.split(" ")[:-1]
617-
618-
if limit is not None:
619-
return " ".join(parts[:limit])
620-
621-
return " ".join(parts)
617+
return " ".join(parts[:limit])
622618

623619
def _get_default_ui(self) -> UI:
624620
from cleo.ui.progress_bar import ProgressBar

src/cleo/color.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def __init__(
5252
if option not in self.AVAILABLE_OPTIONS:
5353
raise ValueError(
5454
f'"{option}" is not a valid color option. '
55-
f"It must be one of {', '.join(self.AVAILABLE_OPTIONS.keys())}"
55+
f"It must be one of {', '.join(self.AVAILABLE_OPTIONS)}"
5656
)
5757

5858
self._options[option] = self.AVAILABLE_OPTIONS[option]
@@ -114,7 +114,7 @@ def _parse_color(self, color: str, background: bool) -> str:
114114
if color not in self.COLORS:
115115
raise CleoValueError(
116116
f'"{color}" is an invalid color.'
117-
f" It must be one of {', '.join(self.COLORS.keys())}"
117+
f" It must be one of {', '.join(self.COLORS)}"
118118
)
119119

120120
return str(self.COLORS[color][int(background)])

src/cleo/commands/base_command.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def __init__(self) -> None:
3636
self.configure()
3737

3838
for i, usage in enumerate(self.usages):
39-
if self.name and usage.find(self.name) != 0:
39+
if self.name and not usage.startswith(self.name):
4040
self.usages[i] = f"{self.name} {usage}"
4141

4242
@property
@@ -85,7 +85,7 @@ def configure(self) -> None:
8585
"""
8686

8787
def execute(self, io: IO) -> int:
88-
raise NotImplementedError()
88+
raise NotImplementedError
8989

9090
def interact(self, io: IO) -> None:
9191
"""
@@ -114,12 +114,7 @@ def run(self, io: IO) -> int:
114114

115115
io.input.validate()
116116

117-
status_code = self.execute(io)
118-
119-
if status_code is None:
120-
status_code = 0
121-
122-
return status_code
117+
return self.execute(io) or 0
123118

124119
def merge_application_definition(self, merge_args: bool = True) -> None:
125120
if self._application is None:

src/cleo/commands/command.py

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64,35 +64,29 @@ def execute(self, io: IO) -> int:
6464

6565
def handle(self) -> int:
6666
"""
67-
Executes the command.
67+
Execute the command.
6868
"""
69-
raise NotImplementedError()
69+
raise NotImplementedError
7070

7171
def call(self, name: str, args: str | None = None) -> int:
7272
"""
7373
Call another command.
7474
"""
75-
if args is None:
76-
args = ""
77-
78-
input = StringInput(args)
7975
assert self.application is not None
8076
command = self.application.get(name)
8177

82-
return self.application._run_command(command, self._io.with_input(input))
78+
return self.application._run_command(
79+
command, self._io.with_input(StringInput(args or ""))
80+
)
8381

8482
def call_silent(self, name: str, args: str | None = None) -> int:
8583
"""
8684
Call another command silently.
8785
"""
88-
if args is None:
89-
args = ""
90-
91-
input = StringInput(args)
9286
assert self.application is not None
9387
command = self.application.get(name)
9488

95-
return self.application._run_command(command, NullIO(input))
89+
return self.application._run_command(command, NullIO(StringInput(args or "")))
9690

9791
def argument(self, name: str) -> Any:
9892
"""
@@ -166,7 +160,7 @@ def choice(
166160
def create_question(
167161
self,
168162
question: str,
169-
type: Literal["choice"] | Literal["confirmation"] | None = None,
163+
type: Literal["choice", "confirmation"] | None = None,
170164
**kwargs: Any,
171165
) -> Question:
172166
"""
@@ -176,14 +170,13 @@ def create_question(
176170
from cleo.ui.confirmation_question import ConfirmationQuestion
177171
from cleo.ui.question import Question
178172

179-
if not type:
180-
return Question(question, **kwargs)
173+
if type == "confirmation":
174+
return ConfirmationQuestion(question, **kwargs)
181175

182176
if type == "choice":
183177
return ChoiceQuestion(question, **kwargs)
184178

185-
if type == "confirmation":
186-
return ConfirmationQuestion(question, **kwargs)
179+
return Question(question, **kwargs)
187180

188181
def table(
189182
self,

src/cleo/commands/completions_command.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import re
88
import subprocess
99

10+
from pathlib import Path
1011
from typing import TYPE_CHECKING
1112
from typing import ClassVar
1213

@@ -142,7 +143,7 @@ def _get_script_name_and_path(self) -> tuple[str, str]:
142143
# we incorrectly infer `script_name` as `__main__.py`
143144
script_name = self._io.input.script_name or inspect.stack()[-1][1]
144145
script_path = posixpath.realpath(script_name)
145-
script_name = os.path.basename(script_path)
146+
script_name = Path(script_path).name
146147

147148
return script_name, script_path
148149

@@ -162,7 +163,7 @@ def render_bash(self) -> str:
162163
cmds = []
163164
cmds_opts = []
164165
for cmd in sorted(self.application.all().values(), key=lambda c: c.name or ""):
165-
if cmd.hidden or not cmd.enabled or not cmd.name:
166+
if cmd.hidden or not (cmd.enabled and cmd.name):
166167
continue
167168
command_name = shell_quote(cmd.name) if " " in cmd.name else cmd.name
168169
cmds.append(command_name)
@@ -207,7 +208,7 @@ def sanitize(s: str) -> str:
207208
cmds = []
208209
cmds_opts = []
209210
for cmd in sorted(self.application.all().values(), key=lambda c: c.name or ""):
210-
if cmd.hidden or not cmd.enabled or not cmd.name:
211+
if cmd.hidden or not (cmd.enabled and cmd.name):
211212
continue
212213
command_name = shell_quote(cmd.name) if " " in cmd.name else cmd.name
213214
cmds.append(self._zsh_describe(command_name, sanitize(cmd.description)))
@@ -287,11 +288,11 @@ def get_shell_type(self) -> str:
287288
"Please specify your shell type by passing it as the first argument."
288289
)
289290

290-
return os.path.basename(shell)
291+
return Path(shell).name
291292

292293
def _generate_function_name(self, script_name: str, script_path: str) -> str:
293294
sanitized_name = self._sanitize_for_function_name(script_name)
294-
md5_hash = hashlib.md5(script_path.encode()).hexdigest()[0:16]
295+
md5_hash = hashlib.md5(script_path.encode()).hexdigest()[:16]
295296
return f"_{sanitized_name}_{md5_hash}_complete"
296297

297298
def _sanitize_for_function_name(self, name: str) -> str:

src/cleo/descriptors/application_description.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,9 @@ def _sort_commands(
7878
key = self._application.extract_namespace(name, 1) or "_global"
7979
namespaced_commands[key][name] = command
8080

81-
namespaced_commands_lst: dict[str, list[tuple[str, Command]]] = {}
82-
for namespace, commands in namespaced_commands.items():
83-
namespaced_commands_lst[namespace] = sorted(
84-
commands.items(), key=lambda x: x[0]
85-
)
81+
namespaced_commands_list: dict[str, list[tuple[str, Command]]] = {
82+
namespace: sorted(commands.items())
83+
for namespace, commands in namespaced_commands.items()
84+
}
8685

87-
return sorted(namespaced_commands_lst.items(), key=lambda x: x[0])
86+
return sorted(namespaced_commands_list.items())

src/cleo/descriptors/descriptor.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,16 @@ def _write(self, content: str, decorated: bool = True) -> None:
3636
)
3737

3838
def _describe_argument(self, argument: Argument, **options: Any) -> None:
39-
raise NotImplementedError()
39+
raise NotImplementedError
4040

4141
def _describe_option(self, option: Option, **options: Any) -> None:
42-
raise NotImplementedError()
42+
raise NotImplementedError
4343

4444
def _describe_definition(self, definition: Definition, **options: Any) -> None:
45-
raise NotImplementedError()
45+
raise NotImplementedError
4646

4747
def _describe_command(self, command: Command, **options: Any) -> None:
48-
raise NotImplementedError()
48+
raise NotImplementedError
4949

5050
def _describe_application(self, application: Application, **options: Any) -> None:
51-
raise NotImplementedError()
51+
raise NotImplementedError

src/cleo/descriptors/text_descriptor.py

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,7 @@ def _describe_application(self, application: Application, **options: Any) -> Non
169169

170170
self._describe_definition(Definition(application.definition.options), **options)
171171

172-
self._write("\n")
173-
self._write("\n")
172+
self._write("\n\n")
174173

175174
commands = description.commands
176175
namespaces = description.namespaces
@@ -181,7 +180,7 @@ def _describe_application(self, application: Application, **options: Any) -> Non
181180
commands[name] = description.command(name)
182181

183182
# calculate max width based on available commands per namespace
184-
all_commands = list(commands.keys())
183+
all_commands = list(commands)
185184
for namespace in namespaces.values():
186185
all_commands += namespace["commands"]
187186

@@ -223,23 +222,18 @@ def _describe_application(self, application: Application, **options: Any) -> Non
223222
self._write("\n")
224223

225224
def _format_default_value(self, default: Any) -> str:
226-
new_default: Any
227225
if isinstance(default, str):
228226
default = Formatter.escape(default)
229227
elif isinstance(default, list):
230-
new_default = []
231-
for value in default:
232-
if isinstance(value, str):
233-
new_default.append(Formatter.escape(value))
234-
235-
default = new_default
228+
default = [
229+
Formatter.escape(value) for value in default if isinstance(value, str)
230+
]
236231
elif isinstance(default, dict):
237-
new_default = {}
238-
for key, value in default.items():
239-
if isinstance(value, str):
240-
new_default[key] = Formatter.escape(value)
241-
242-
default = new_default
232+
default = {
233+
key: Formatter.escape(value)
234+
for key, value in default.items()
235+
if isinstance(value, str)
236+
}
243237

244238
return json.dumps(default).replace("\\\\", "\\")
245239

@@ -261,7 +255,7 @@ def _calculate_total_width_for_options(self, options: list[Option]) -> int:
261255
return total_width
262256

263257
def _get_column_width(self, commands: Sequence[Command | str]) -> int:
264-
widths = []
258+
widths: list[int] = []
265259

266260
for command in commands:
267261
if isinstance(command, Command):
@@ -278,10 +272,9 @@ def _get_column_width(self, commands: Sequence[Command | str]) -> int:
278272
return max(widths) + 2
279273

280274
def _get_command_aliases_text(self, command: Command) -> str:
281-
text = ""
282275
aliases = command.aliases
283276

284277
if aliases:
285-
text = f"[{ '|'.join(aliases) }] "
278+
return f"[{ '|'.join(aliases) }] "
286279

287-
return text
280+
return ""

src/cleo/events/event_dispatcher.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def __init__(self) -> None:
1818

1919
def dispatch(self, event: Event, event_name: str | None = None) -> Event:
2020
if event_name is None:
21-
event_name = event.__class__.__name__
21+
event_name = type(event).__name__
2222

2323
listeners = cast("list[Listener]", self.get_listeners(event_name))
2424

@@ -58,11 +58,7 @@ def get_listener_priority(self, event_name: str, listener: Listener) -> int | No
5858

5959
def has_listeners(self, event_name: str | None = None) -> bool:
6060
if event_name is not None:
61-
if event_name not in self._listeners:
62-
return False
63-
64-
return bool(self._listeners[event_name])
65-
61+
return bool(self._listeners.get(event_name))
6662
return any(self._listeners.values())
6763

6864
def add_listener(
@@ -92,10 +88,8 @@ def _sort_listeners(self, event_name: str) -> None:
9288
"""
9389
Sorts the internal list of listeners for the given event by priority.
9490
"""
95-
self._sorted[event_name] = []
91+
prioritized_listeners = self._listeners[event_name]
92+
sorted_listeners = self._sorted[event_name] = []
9693

97-
for _, listeners in sorted(
98-
self._listeners[event_name].items(), key=lambda t: -t[0]
99-
):
100-
for listener in listeners:
101-
self._sorted[event_name].append(listener)
94+
for priority in sorted(prioritized_listeners, reverse=True):
95+
sorted_listeners.extend(prioritized_listeners[priority])

0 commit comments

Comments
 (0)