Skip to content

ui.ui_helper

IUiHelper

Bases: Protocol

Protocol for helpers that mediate user interaction.

Concrete implementations are responsible for presenting messages, collecting input and offering higher level prompts such as lists or yes/no questions. This protocol is intentionally small so that it can be fulfilled by both interactive console UIs and non-interactive test doubles.

print

print(message: str) -> None

Display a message to the user without expecting a response.

Source code in src/clabe/ui/ui_helper.py
27
28
def print(self, message: str) -> None:
    """Display a message to the user without expecting a response."""

input

input(prompt: str) -> str

Prompt the user for free‑form text input and return the reply.

Source code in src/clabe/ui/ui_helper.py
30
31
def input(self, prompt: str) -> str:
    """Prompt the user for free‑form text input and return the reply."""

prompt_pick_from_list

prompt_pick_from_list(
    value: List[str], prompt: str, **kwargs
) -> Optional[str]

Prompt the user to pick a single item from value.

Implementations should return the chosen item or None when the selection is cancelled.

Source code in src/clabe/ui/ui_helper.py
33
34
35
36
37
38
def prompt_pick_from_list(self, value: List[str], prompt: str, **kwargs) -> Optional[str]:
    """Prompt the user to pick a single item from ``value``.

    Implementations should return the chosen item or ``None`` when the
    selection is cancelled.
    """

prompt_yes_no_question

prompt_yes_no_question(prompt: str) -> bool

Ask the user a yes/no question and return their choice.

Source code in src/clabe/ui/ui_helper.py
40
41
def prompt_yes_no_question(self, prompt: str) -> bool:
    """Ask the user a yes/no question and return their choice."""

prompt_text

prompt_text(prompt: str) -> str

Prompt the user for a short text answer and return it.

Source code in src/clabe/ui/ui_helper.py
43
44
def prompt_text(self, prompt: str) -> str:
    """Prompt the user for a short text answer and return it."""

prompt_float

prompt_float(prompt: str) -> float

Prompt the user for a floating‑point number and return it.

Source code in src/clabe/ui/ui_helper.py
46
47
def prompt_float(self, prompt: str) -> float:
    """Prompt the user for a floating‑point number and return it."""

NativeUiHelper

NativeUiHelper(
    print_func: _PrintFunc = _DEFAULT_PRINT_FUNC,
    input_func: _InputFunc = _DEFAULT_INPUT_FUNC,
)

Bases: _UiHelperBase

Default implementation of the UI helper for user interaction.

Provides a concrete implementation using standard console input/output for user interactions.

Methods:

Name Description
print

Prints a message to the console

input

Prompts the user for input from the console

prompt_pick_from_list

Prompts the user to select from a list

prompt_yes_no_question

Prompts the user with a yes/no question

prompt_text

Prompts the user for text input

prompt_float

Prompts the user for a floating-point number

Initializes the DefaultUIHelper with custom print and input functions.

Parameters:

Name Type Description Default
print_func _PrintFunc

Custom function for printing messages

_DEFAULT_PRINT_FUNC
input_func _InputFunc

Custom function for receiving user input

_DEFAULT_INPUT_FUNC
Source code in src/clabe/ui/ui_helper.py
189
190
191
192
193
194
195
196
197
198
199
200
def __init__(
    self, print_func: _PrintFunc = _DEFAULT_PRINT_FUNC, input_func: _InputFunc = _DEFAULT_INPUT_FUNC
) -> None:
    """
    Initializes the DefaultUIHelper with custom print and input functions.

    Args:
        print_func: Custom function for printing messages
        input_func: Custom function for receiving user input
    """
    self._print = print_func
    self._input = input_func

print

print(message: str) -> None

Prints a message using the configured print function.

Parameters:

Name Type Description Default
message str

The message to print

required

Returns:

Name Type Description
Any None

The result of the print function (usually None)

Source code in src/clabe/ui/ui_helper.py
202
203
204
205
206
207
208
209
210
211
212
def print(self, message: str) -> None:
    """
    Prints a message using the configured print function.

    Args:
        message: The message to print

    Returns:
        Any: The result of the print function (usually None)
    """
    return self._print(message)

input

input(prompt: str) -> str

Prompts the user for input using the configured input function.

Parameters:

Name Type Description Default
prompt str

The prompt message to display

required

Returns:

Name Type Description
str str

The user input received from the input function

Source code in src/clabe/ui/ui_helper.py
214
215
216
217
218
219
220
221
222
223
224
def input(self, prompt: str) -> str:
    """
    Prompts the user for input using the configured input function.

    Args:
        prompt: The prompt message to display

    Returns:
        str: The user input received from the input function
    """
    return self._input(prompt)

prompt_pick_from_list

prompt_pick_from_list(
    value: List[str],
    prompt: str,
    *,
    allow_0_as_none: bool = True,
    zero_label: str = "None",
    **kwargs,
) -> Optional[str]

Prompts the user to pick an item from a list.

Displays a numbered list of options and prompts the user to select one by entering the corresponding number.

Parameters:

Name Type Description Default
value List[str]

The list of items to choose from

required
prompt str

The prompt message

required
allow_0_as_none bool

Whether to allow 0 as a choice for None

True

Returns:

Type Description
Optional[str]

Optional[str]: The selected item or None

Example
helper = DefaultUIHelper()
files = ["file1.txt", "file2.txt", "file3.txt"]
selected = helper.prompt_pick_from_list(files, "Choose a file:")

# With None option disabled
selected = helper.prompt_pick_from_list(
    files, "Must choose a file:", allow_0_as_none=False
)
Source code in src/clabe/ui/ui_helper.py
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
def prompt_pick_from_list(
    self, value: List[str], prompt: str, *, allow_0_as_none: bool = True, zero_label: str = "None", **kwargs
) -> Optional[str]:
    """
    Prompts the user to pick an item from a list.

    Displays a numbered list of options and prompts the user to select
    one by entering the corresponding number.

    Args:
        value: The list of items to choose from
        prompt: The prompt message
        allow_0_as_none: Whether to allow 0 as a choice for None

    Returns:
        Optional[str]: The selected item or None

    Example:
        ```python
        helper = DefaultUIHelper()
        files = ["file1.txt", "file2.txt", "file3.txt"]
        selected = helper.prompt_pick_from_list(files, "Choose a file:")

        # With None option disabled
        selected = helper.prompt_pick_from_list(
            files, "Must choose a file:", allow_0_as_none=False
        )
        ```
    """
    while True:
        try:
            self.print(prompt)
            if allow_0_as_none:
                self.print(f"0: {zero_label}")
            for i, item in enumerate(value):
                self.print(f"{i + 1}: {item}")
            choice = int(input("Choice: "))
            if choice < 0 or choice >= len(value) + 1:
                raise ValueError
            if choice == 0:
                if allow_0_as_none:
                    return None
                else:
                    raise ValueError
            return value[choice - 1]
        except ValueError as e:
            logger.info("Invalid choice. Try again. %s", e)

prompt_yes_no_question

prompt_yes_no_question(prompt: str) -> bool

Prompts the user with a yes/no question.

Continues prompting until a valid yes/no response is received.

Parameters:

Name Type Description Default
prompt str

The question to ask

required

Returns:

Name Type Description
bool bool

True for yes, False for no

Example
helper = DefaultUIHelper()

if helper.prompt_yes_no_question("Save changes?"):
    save_data()

proceed = helper.prompt_yes_no_question("Delete all files?")
if proceed:
    delete_files()
Source code in src/clabe/ui/ui_helper.py
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
def prompt_yes_no_question(self, prompt: str) -> bool:
    """
    Prompts the user with a yes/no question.

    Continues prompting until a valid yes/no response is received.

    Args:
        prompt: The question to ask

    Returns:
        bool: True for yes, False for no

    Example:
        ```python
        helper = DefaultUIHelper()

        if helper.prompt_yes_no_question("Save changes?"):
            save_data()

        proceed = helper.prompt_yes_no_question("Delete all files?")
        if proceed:
            delete_files()
        ```
    """
    while True:
        reply = input(prompt + " (Y\\N): ").upper()
        if reply == "Y" or reply == "1":
            return True
        elif reply == "N" or reply == "0":
            return False
        else:
            self.print("Invalid input. Please enter 'Y' or 'N'.")

prompt_text

prompt_text(prompt: str) -> str

Prompts the user for text input.

Simple text input prompt that returns the user's input as a string.

Parameters:

Name Type Description Default
prompt str

The prompt message

required

Returns:

Name Type Description
str str

The user input

Example
helper = DefaultUIHelper()

name = helper.prompt_text("Enter your name: ")
description = helper.prompt_text("Enter description: ")
path = helper.prompt_text("Enter file path: ")
Source code in src/clabe/ui/ui_helper.py
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
def prompt_text(self, prompt: str) -> str:
    """
    Prompts the user for text input.

    Simple text input prompt that returns the user's input as a string.

    Args:
        prompt: The prompt message

    Returns:
        str: The user input

    Example:
        ```python
        helper = DefaultUIHelper()

        name = helper.prompt_text("Enter your name: ")
        description = helper.prompt_text("Enter description: ")
        path = helper.prompt_text("Enter file path: ")
        ```
    """
    notes = str(input(prompt))
    return notes

prompt_float

prompt_float(prompt: str) -> float

Prompts the user for a float input.

Continues prompting until a valid float value is entered.

Parameters:

Name Type Description Default
prompt str

The prompt message

required

Returns:

Name Type Description
float float

The parsed user input

Example
helper = DefaultUIHelper()

temperature = helper.prompt_float("Enter temperature: ")
weight = helper.prompt_float("Enter weight in kg: ")
price = helper.prompt_float("Enter price: $")
Source code in src/clabe/ui/ui_helper.py
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
def prompt_float(self, prompt: str) -> float:
    """
    Prompts the user for a float input.

    Continues prompting until a valid float value is entered.

    Args:
        prompt: The prompt message

    Returns:
        float: The parsed user input

    Example:
        ```python
        helper = DefaultUIHelper()

        temperature = helper.prompt_float("Enter temperature: ")
        weight = helper.prompt_float("Enter weight in kg: ")
        price = helper.prompt_float("Enter price: $")
        ```
    """
    while True:
        try:
            value = float(input(prompt))
            return value
        except ValueError:
            self.print("Invalid input. Please enter a valid float.")

prompt_field_from_input

prompt_field_from_input(
    model: Type[_TModel],
    field_name: str,
    default: Optional[_T] = None,
) -> Optional[_T]

Prompts the user to input a value for a specific field in a model.

Uses the model's field information to prompt for input and validates the entered value against the field's type annotation.

Parameters:

Name Type Description Default
model Type[_TModel]

The model containing the field

required
field_name str

The name of the field

required
default Optional[_T]

The default value if no input is provided

None

Returns:

Type Description
Optional[_T]

Optional[_T]: The validated input value or the default value

Example
from pydantic import BaseModel, Field

class UserModel(BaseModel):
    name: str = Field(description="User's full name")
    age: int = Field(description="User's age in years")

# Prompt for name field
name = prompt_field_from_input(UserModel, "name", "Anonymous")

# Prompt for age field
age = prompt_field_from_input(UserModel, "age", 18)
Source code in src/clabe/ui/ui_helper.py
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
def prompt_field_from_input(model: Type[_TModel], field_name: str, default: Optional[_T] = None) -> Optional[_T]:
    """
    Prompts the user to input a value for a specific field in a model.

    Uses the model's field information to prompt for input and validates the
    entered value against the field's type annotation.

    Args:
        model: The model containing the field
        field_name: The name of the field
        default: The default value if no input is provided

    Returns:
        Optional[_T]: The validated input value or the default value

    Example:
        ```python
        from pydantic import BaseModel, Field

        class UserModel(BaseModel):
            name: str = Field(description="User's full name")
            age: int = Field(description="User's age in years")

        # Prompt for name field
        name = prompt_field_from_input(UserModel, "name", "Anonymous")

        # Prompt for age field
        age = prompt_field_from_input(UserModel, "age", 18)
        ```
    """
    _field = model.model_fields[field_name]
    _type_adaptor: TypeAdapter = TypeAdapter(_field.annotation)
    value: Optional[_T] | str
    _in = input(f"Enter {field_name} ({_field.description}): ")
    value = _in if _in != "" else default
    return _type_adaptor.validate_python(value)