Skip to content

Commit 31053fc

Browse files
committed
no more inquirer
1 parent efb195b commit 31053fc

File tree

5 files changed

+39
-110
lines changed

5 files changed

+39
-110
lines changed

codeflash/cli_cmds/cli_common.py

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@
22

33
import shutil
44
import sys
5-
from typing import Callable, cast
6-
7-
import click
8-
import inquirer
95

106
from codeflash.cli_cmds.console import console, logger
117

@@ -20,29 +16,6 @@ def apologize_and_exit() -> None:
2016
sys.exit(1)
2117

2218

23-
def inquirer_wrapper(func: Callable[..., str | bool], *args: str | bool, **kwargs: str | bool) -> str | bool:
24-
new_args = []
25-
new_kwargs = {}
26-
27-
if len(args) == 1:
28-
message = str(args[0])
29-
else:
30-
message = str(kwargs["message"])
31-
new_kwargs = kwargs.copy()
32-
split_messages = split_string_to_cli_width(message, is_confirm=func == inquirer.confirm)
33-
for split_message in split_messages[:-1]:
34-
click.echo(split_message)
35-
36-
last_message = split_messages[-1]
37-
38-
if len(args) == 1:
39-
new_args.append(last_message)
40-
else:
41-
new_kwargs["message"] = last_message
42-
43-
return func(*new_args, **new_kwargs)
44-
45-
4619
def split_string_to_cli_width(string: str, is_confirm: bool = False) -> list[str]: # noqa: FBT001, FBT002
4720
cli_width, _ = shutil.get_terminal_size()
4821
# split string to lines that accommodate "[?] " prefix
@@ -62,21 +35,6 @@ def split_string_to_cli_width(string: str, is_confirm: bool = False) -> list[str
6235
return lines
6336

6437

65-
def inquirer_wrapper_path(*args: str, **kwargs: str) -> dict[str, str] | None:
66-
new_args = []
67-
message = kwargs["message"]
68-
new_kwargs = kwargs.copy()
69-
split_messages = split_string_to_cli_width(message)
70-
for split_message in split_messages[:-1]:
71-
click.echo(split_message)
72-
73-
last_message = split_messages[-1]
74-
new_kwargs["message"] = last_message
75-
new_args.append(args[0])
76-
77-
return cast("dict[str, str]", inquirer.prompt([inquirer.Path(*new_args, **new_kwargs)]))
78-
79-
8038
def split_string_to_fit_width(string: str, width: int) -> list[str]:
8139
words = string.split()
8240
lines = []

codeflash/cli_cmds/cmd_init.py

Lines changed: 30 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,13 @@
1111

1212
import click
1313
import git
14-
import inquirer
15-
import inquirer.themes
1614
import tomlkit
1715
from git import InvalidGitRepositoryError, Repo
1816
from pydantic.dataclasses import dataclass
17+
from rich.prompt import Confirm, Prompt
1918

2019
from codeflash.api.cfapi import is_github_app_installed_on_repo
21-
from codeflash.cli_cmds.cli_common import apologize_and_exit, inquirer_wrapper, inquirer_wrapper_path
20+
from codeflash.cli_cmds.cli_common import apologize_and_exit
2221
from codeflash.cli_cmds.console import console, logger
2322
from codeflash.code_utils.compat import LF
2423
from codeflash.code_utils.config_parser import parse_config_file
@@ -185,23 +184,20 @@ def collect_setup_info() -> SetupInfo:
185184
custom_dir_option = "enter a custom directory…"
186185
module_subdir_options = [*valid_module_subdirs, curdir_option, custom_dir_option]
187186

188-
module_root_answer = inquirer_wrapper(
189-
inquirer.list_input,
190-
message="Which Python module do you want me to optimize going forward? (Usually the top-most directory with "
191-
"all of your Python source code). Use arrow keys to select",
187+
module_root_answer = Prompt.ask(
188+
"Which Python module do you want me to optimize going forward? (Usually the top-most directory with "
189+
"all of your Python source code)",
192190
choices=module_subdir_options,
193191
default=(project_name if project_name in module_subdir_options else module_subdir_options[0]),
194192
)
195193
if module_root_answer == curdir_option:
196194
module_root = "."
197195
elif module_root_answer == custom_dir_option:
198-
custom_module_root_answer = inquirer_wrapper_path(
199-
"path",
200-
message=f"Enter the path to your module directory inside {Path(curdir).resolve()}{os.path.sep} ",
201-
path_type=inquirer.Path.DIRECTORY,
196+
custom_module_root_answer = Prompt.ask(
197+
f"Enter the path to your module directory inside {Path(curdir).resolve()}{os.path.sep}"
202198
)
203199
if custom_module_root_answer:
204-
module_root = Path(custom_module_root_answer["path"])
200+
module_root = Path(custom_module_root_answer)
205201
else:
206202
apologize_and_exit()
207203
else:
@@ -216,9 +212,8 @@ def collect_setup_info() -> SetupInfo:
216212
test_subdir_options.append(create_for_me_option)
217213
custom_dir_option = "enter a custom directory…"
218214
test_subdir_options.append(custom_dir_option)
219-
tests_root_answer = inquirer_wrapper(
220-
inquirer.list_input,
221-
message="Where are your tests located? "
215+
tests_root_answer = Prompt.ask(
216+
"Where are your tests located? "
222217
f"(If you don't have any tests yet, I can create an empty tests{os.pathsep} directory for you)",
223218
choices=test_subdir_options,
224219
default=(default_tests_subdir if default_tests_subdir in test_subdir_options else test_subdir_options[0]),
@@ -229,13 +224,11 @@ def collect_setup_info() -> SetupInfo:
229224
tests_root.mkdir()
230225
click.echo(f"✅ Created directory {tests_root}{os.path.sep}{LF}")
231226
elif tests_root_answer == custom_dir_option:
232-
custom_tests_root_answer = inquirer_wrapper_path(
233-
"path",
234-
message=f"Enter the path to your tests directory inside {Path(curdir).resolve()}{os.path.sep} ",
235-
path_type=inquirer.Path.DIRECTORY,
227+
custom_tests_root_answer = Prompt.ask(
228+
f"Enter the path to your tests directory inside {Path(curdir).resolve()}{os.path.sep}"
236229
)
237230
if custom_tests_root_answer:
238-
tests_root = Path(curdir) / Path(custom_tests_root_answer["path"])
231+
tests_root = Path(curdir) / Path(custom_tests_root_answer)
239232
else:
240233
apologize_and_exit()
241234
else:
@@ -257,12 +250,10 @@ def collect_setup_info() -> SetupInfo:
257250
autodetected_suffix = (
258251
f" (seems to me you're using {autodetected_test_framework})" if autodetected_test_framework else ""
259252
)
260-
test_framework = inquirer_wrapper(
261-
inquirer.list_input,
262-
message="Which test framework do you use?" + autodetected_suffix,
253+
test_framework = Prompt.ask(
254+
"Which test framework do you use?" + autodetected_suffix,
263255
choices=["pytest", "unittest"],
264256
default=autodetected_test_framework or "pytest",
265-
carousel=True,
266257
)
267258

268259
ph("cli-test-framework-provided", {"test_framework": test_framework})
@@ -285,9 +276,8 @@ def collect_setup_info() -> SetupInfo:
285276
benchmarks_options.append(create_benchmarks_option)
286277
benchmarks_options.append(custom_dir_option)
287278

288-
benchmarks_answer = inquirer_wrapper(
289-
inquirer.list_input,
290-
message="Where are your performance benchmarks located? (benchmarks must be a sub directory of your tests root directory)",
279+
benchmarks_answer = Prompt.ask(
280+
"Where are your performance benchmarks located? (benchmarks must be a sub directory of your tests root directory)",
291281
choices=benchmarks_options,
292282
default=(
293283
default_benchmarks_subdir if default_benchmarks_subdir in benchmarks_options else benchmarks_options[0]
@@ -299,13 +289,11 @@ def collect_setup_info() -> SetupInfo:
299289
benchmarks_root.mkdir(exist_ok=True)
300290
click.echo(f"✅ Created directory {benchmarks_root}{os.path.sep}{LF}")
301291
elif benchmarks_answer == custom_dir_option:
302-
custom_benchmarks_answer = inquirer_wrapper_path(
303-
"path",
304-
message=f"Enter the path to your benchmarks directory inside {tests_root}{os.path.sep} ",
305-
path_type=inquirer.Path.DIRECTORY,
292+
custom_benchmarks_answer = Prompt.ask(
293+
f"Enter the path to your benchmarks directory inside {tests_root}{os.path.sep}"
306294
)
307295
if custom_benchmarks_answer:
308-
benchmarks_root = tests_root / Path(custom_benchmarks_answer["path"])
296+
benchmarks_root = tests_root / Path(custom_benchmarks_answer)
309297
else:
310298
apologize_and_exit()
311299
elif benchmarks_answer == no_benchmarks_option:
@@ -327,12 +315,8 @@ def collect_setup_info() -> SetupInfo:
327315
# carousel=True,
328316
# )
329317

330-
formatter = inquirer_wrapper(
331-
inquirer.list_input,
332-
message="Which code formatter do you use?",
333-
choices=["black", "ruff", "other", "don't use a formatter"],
334-
default="black",
335-
carousel=True,
318+
formatter = Prompt.ask(
319+
"Which code formatter do you use?", choices=["black", "ruff", "other", "don't use a formatter"], default="black"
336320
)
337321

338322
git_remote = ""
@@ -341,12 +325,10 @@ def collect_setup_info() -> SetupInfo:
341325
git_remotes = get_git_remotes(repo)
342326
if git_remotes: # Only proceed if there are remotes
343327
if len(git_remotes) > 1:
344-
git_remote = inquirer_wrapper(
345-
inquirer.list_input,
346-
message="What git remote do you want Codeflash to use for new Pull Requests? ",
328+
git_remote = Prompt.ask(
329+
"What git remote do you want Codeflash to use for new Pull Requests?",
347330
choices=git_remotes,
348331
default="origin",
349-
carousel=True,
350332
)
351333
else:
352334
git_remote = git_remotes[0]
@@ -447,11 +429,8 @@ def check_for_toml_or_setup_file() -> str | None:
447429
ph("cli-no-pyproject-toml-or-setup-py")
448430

449431
# Create a pyproject.toml file because it doesn't exist
450-
create_toml = inquirer_wrapper(
451-
inquirer.confirm,
452-
message="Do you want me to create a pyproject.toml file in the current directory?",
453-
default=True,
454-
show_default=False,
432+
create_toml = Confirm.ask(
433+
"Do you want me to create a pyproject.toml file in the current directory?", default=True
455434
)
456435
if create_toml:
457436
ph("cli-create-pyproject-toml")
@@ -497,20 +476,17 @@ def install_github_actions(override_formatter_check: bool = False) -> None: # n
497476

498477
# Check if the workflow file already exists
499478
if optimize_yaml_path.exists():
500-
confirm_overwrite = inquirer_wrapper(
501-
inquirer.confirm,
502-
message=f"⚡️ GitHub Actions workflow already exists at {optimize_yaml_path}. Overwrite?",
503-
default=False, # Don't overwrite by default
479+
confirm_overwrite = Confirm.ask(
480+
f"⚡️ GitHub Actions workflow already exists at {optimize_yaml_path}. Overwrite?", default=False
504481
)
505482
ph("cli-github-optimization-confirm-workflow-overwrite", {"confirm_overwrite": confirm_overwrite})
506483
if not confirm_overwrite:
507484
click.echo("⏩️ Skipping workflow creation.")
508485
ph("cli-github-workflow-skipped")
509486
return
510487

511-
confirm_creation_yes = inquirer_wrapper(
512-
inquirer.confirm,
513-
message="⚡️Shall I set up a GitHub action that will continuously optimize all new code in GitHub PRs"
488+
confirm_creation_yes = Confirm.ask(
489+
"⚡️Shall I set up a GitHub action that will continuously optimize all new code in GitHub PRs"
514490
" for you? This is the main way of using Codeflash so we highly recommend it",
515491
default=True,
516492
)

codeflash/code_utils/git_utils.py

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@
1212
from typing import TYPE_CHECKING
1313

1414
import git
15-
import inquirer
15+
from rich.prompt import Confirm
1616
from unidiff import PatchSet
1717

18-
from codeflash.cli_cmds.cli_common import inquirer_wrapper
1918
from codeflash.cli_cmds.console import logger
2019
from codeflash.code_utils.config_consts import N_CANDIDATES
2120

@@ -109,11 +108,9 @@ def check_running_in_git_repo(module_root: str) -> bool:
109108

110109
def confirm_proceeding_with_no_git_repo() -> str | bool:
111110
if sys.__stdin__.isatty():
112-
return inquirer_wrapper(
113-
inquirer.confirm,
114-
message="WARNING: I did not find a git repository for your code. If you proceed with running codeflash, "
115-
"optimized code will"
116-
" be written over your current code and you could irreversibly lose your current code. Proceed?",
111+
return Confirm.ask(
112+
"WARNING: I did not find a git repository for your code. If you proceed with running codeflash, "
113+
"optimized code will be written over your current code and you could irreversibly lose your current code. Proceed?",
117114
default=False,
118115
)
119116
# continue running on non-interactive environments, important for GitHub actions
@@ -130,11 +127,9 @@ def check_and_push_branch(repo: git.Repo, wait_for_push: bool = False) -> bool:
130127
if not sys.__stdin__.isatty():
131128
logger.warning("Non-interactive shell detected. Branch will not be pushed.")
132129
return False
133-
if sys.__stdin__.isatty() and inquirer_wrapper(
134-
inquirer.confirm,
135-
message=f"⚡️ In order for me to create PRs, your current branch needs to be pushed. Do you want to push "
136-
f"the branch"
137-
f"'{current_branch}' to the remote repository?",
130+
if sys.__stdin__.isatty() and Confirm.ask(
131+
f"⚡️ In order for me to create PRs, your current branch needs to be pushed. Do you want to push "
132+
f"the branch '{current_branch}' to the remote repository?",
138133
default=False,
139134
):
140135
origin.push(current_branch)

codeflash/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# These version placeholders will be replaced by uv-dynamic-versioning during build.
2-
__version__ = "0.14.7"
2+
__version__ = "0.14.7.post7.dev0+efb195b8"

tests/test_git_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def test_check_running_in_git_repo_not_in_git_repo_non_interactive(self, mock_is
6464

6565
@patch("codeflash.code_utils.git_utils.git.Repo")
6666
@patch("codeflash.code_utils.git_utils.sys.__stdin__.isatty", return_value=True)
67-
@patch("codeflash.code_utils.git_utils.inquirer.confirm", return_value=True)
67+
@patch("codeflash.code_utils.git_utils.Confirm.ask", return_value=True)
6868
def test_check_and_push_branch(self, mock_confirm, mock_isatty, mock_repo):
6969
mock_repo_instance = mock_repo.return_value
7070
mock_repo_instance.active_branch.name = "test-branch"

0 commit comments

Comments
 (0)