Skip to content

🎨 Palette: Add validation to interactive prompts#127

Merged
abhimehro merged 1 commit intomainfrom
palette-cli-validation-9923405677569176900
Jan 27, 2026
Merged

🎨 Palette: Add validation to interactive prompts#127
abhimehro merged 1 commit intomainfrom
palette-cli-validation-9923405677569176900

Conversation

@google-labs-jules
Copy link

🎨 Palette: Add validation to interactive prompts

💡 What: Added immediate input validation to the CLI interactive prompts.
🎯 Why: To prevent users from waiting for cache warm-up (potentially long) only to fail due to a typo in the Profile ID or Token.
♿ Accessibility: Provides clear, immediate error messages ("❌ Value cannot be empty") instead of generic failures.


PR created automatically by Jules for task 9923405677569176900 started by @abhimehro

- Added `get_valid_input` helper for robust interactive prompts
- Integrated validation for Profile ID and API Token in `main()`
- Refactored `validate_profile_id` to support silent validation
- Added tests for new validation logic

This prevents long wait times before failure due to simple typos in interactive mode.
@google-labs-jules
Copy link
Author

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@trunk-io
Copy link

trunk-io bot commented Jan 23, 2026

Merging to main in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

monkeypatch.setattr(m, "log", mock_log)

# Invalid ID with logging enabled (default)
assert m.validate_profile_id("invalid spaces") is False

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.

# Invalid ID with logging enabled (default)
assert m.validate_profile_id("invalid spaces") is False
assert mock_log.error.called

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
mock_log.reset_mock()

# Invalid ID with logging disabled
assert m.validate_profile_id("invalid spaces", log_errors=False) is False

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.

# Invalid ID with logging disabled
assert m.validate_profile_id("invalid spaces", log_errors=False) is False
assert not mock_log.error.called

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.

result = m.get_valid_input("Prompt: ", validator, "Error message")

assert result == "valid"

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
result = m.get_valid_input("Prompt: ", validator, "Error message")

assert result == "valid"
assert input_mock.call_count == 3

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.

# Check output for error messages
captured = capsys.readouterr()
assert "Value cannot be empty" in captured.out

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
# Check output for error messages
captured = capsys.readouterr()
assert "Value cannot be empty" in captured.out
assert "Error message" in captured.out

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.

result = m.get_valid_input("Password: ", validator, "Error", is_password=True)

assert result == "secret"

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
return False
return True

def get_valid_input(prompt: str, validator: callable, error_msg: str, is_password: bool = False) -> str:

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Line too long (104/100) Warning

Line too long (104/100)
f"{Colors.BOLD}Enter Control D API Token:{Colors.ENDC} ",
validate_token,
"Token seems too short. Please check your API token.",
is_password=True

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

More than one statement on a single line Warning

More than one statement on a single line
assert input_mock.call_count == 3

# Check output for error messages
captured = capsys.readouterr()

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Missing function or method docstring Warning test

Missing function or method docstring
result = m.get_valid_input("Password: ", validator, "Error", is_password=True)

assert result == "secret"
getpass_mock.assert_called_once()

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Missing function or method docstring Warning test

Missing function or method docstring
test_main.py Outdated

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Missing function or method docstring Warning test

Missing function or method docstring
return True

def validate_profile_id(profile_id: str) -> bool:
def validate_profile_id(profile_id: str, log_errors: bool = True) -> bool:

Check warning

Code scanning / Pylint (reported by Codacy)

Missing function docstring Warning

Missing function docstring
return False
return True

def get_valid_input(prompt: str, validator: callable, error_msg: str, is_password: bool = False) -> str:

Check warning

Code scanning / Pylint (reported by Codacy)

Line too long (104/100) Warning

Line too long (104/100)

t_input = get_valid_input(
f"{Colors.BOLD}Enter Control D API Token:{Colors.ENDC} ",
validate_token,

Check warning

Code scanning / Pylint (reported by Codacy)

Missing function docstring Warning

Missing function docstring
f"{Colors.BOLD}Enter Control D API Token:{Colors.ENDC} ",
validate_token,
"Token seems too short. Please check your API token.",
is_password=True

Check warning

Code scanning / Pylint (reported by Codacy)

More than one statement on a single line Warning

More than one statement on a single line
main.py Outdated

Check warning

Code scanning / Pylint (reported by Codacy)

Missing function docstring Warning

Missing function docstring
assert input_mock.call_count == 3

# Check output for error messages
captured = capsys.readouterr()

Check warning

Code scanning / Pylint (reported by Codacy)

Missing function docstring Warning test

Missing function docstring
result = m.get_valid_input("Password: ", validator, "Error", is_password=True)

assert result == "secret"
getpass_mock.assert_called_once()

Check warning

Code scanning / Pylint (reported by Codacy)

Missing function docstring Warning test

Missing function docstring
test_main.py Outdated

Check warning

Code scanning / Pylint (reported by Codacy)

Missing function docstring Warning test

Missing function docstring
if is_password:
value = getpass.getpass(prompt).strip()
else:
value = input(prompt).strip()

Check notice

Code scanning / Bandit (reported by Codacy)

The input method in Python 2 will read from standard input, evaluate and run the resulting string as python source code. This is similar, though in many ways worse, then using eval. On Python 2, use raw_input instead, input is safe in Python 3. Note

The input method in Python 2 will read from standard input, evaluate and run the resulting string as python source code. This is similar, though in many ways worse, then using eval. On Python 2, use raw_input instead, input is safe in Python 3.

# Case 10: get_valid_input works with getpass
def test_get_valid_input_password(monkeypatch):
m = reload_main_with_env(monkeypatch)

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
monkeypatch.setattr('getpass.getpass', getpass_mock)

validator = lambda x: True

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.

validator = lambda x: True

result = m.get_valid_input("Password: ", validator, "Error", is_password=True)

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
test_main.py Outdated

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
test_main.py Outdated

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
test_main.py Outdated

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
test_main.py Outdated

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
test_main.py Outdated

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
@abhimehro abhimehro marked this pull request as ready for review January 27, 2026 07:25
Copilot AI review requested due to automatic review settings January 27, 2026 07:25
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds immediate validation for interactive CLI prompts to catch invalid profile IDs and tokens before any long-running operations, improving UX and error clarity.

Changes:

  • Extended validate_profile_id with a log_errors flag to support silent validation in interactive flows while preserving existing logging behavior for other callers.
  • Introduced a get_valid_input helper that wraps input()/getpass.getpass() in a validation loop with clear, colored error messages and integrated it into the profile ID and token prompts in main().
  • Added unit tests for the new behavior and documented the pattern in .Jules/palette.md under “Immediate CLI Input Validation”.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
main.py Adds log_errors to validate_profile_id, defines get_valid_input, and rewires interactive profile ID and token prompts to use the new helper for immediate validation.
test_main.py Extends test coverage to verify validate_profile_id’s logging toggle and the new get_valid_input behavior for both normal and password-style input.
.Jules/palette.md Documents the new interactive validation pattern and codifies get_valid_input as the preferred wrapper for prompting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

return False
return True

def get_valid_input(prompt: str, validator: callable, error_msg: str, is_password: bool = False) -> str:
Copy link

Copilot AI Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type annotation for validator uses the built-in callable, which isn't a proper typing hint and won't be understood correctly by static type checkers; prefer using typing.Callable[[str], bool] (or a suitable Callable signature) for clearer intent and better tooling support.

Copilot uses AI. Check for mistakes.
@abhimehro abhimehro merged commit 6cef806 into main Jan 27, 2026
23 of 24 checks passed
@abhimehro abhimehro deleted the palette-cli-validation-9923405677569176900 branch January 27, 2026 13:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants