Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions questionary/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from questionary.prompts.rawselect import rawselect
from questionary.prompts.select import select
from questionary.prompts.text import text
from questionary.prompts.date import date
from questionary.question import Question

__version__ = questionary.version.__version__
Expand All @@ -39,6 +40,7 @@
"rawselect",
"select",
"text",
"date",
# utility methods
"print",
"form",
Expand Down
2 changes: 2 additions & 0 deletions questionary/prompts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
from questionary.prompts import rawselect
from questionary.prompts import select
from questionary.prompts import text
from questionary.prompts import date

AVAILABLE_PROMPTS = {
"autocomplete": autocomplete.autocomplete,
"confirm": confirm.confirm,
"text": text.text,
"date": date.date,
"select": select.select,
"rawselect": rawselect.rawselect,
"password": password.password,
Expand Down
98 changes: 98 additions & 0 deletions questionary/prompts/date.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
from typing import Any, Optional
from datetime import datetime

from questionary import Style
from questionary.constants import DEFAULT_QUESTION_PREFIX
from questionary.prompts import text
from questionary.question import Question


def date(
message: str,
default: Optional[str] = None,
validate: Any = None,
qmark: str = DEFAULT_QUESTION_PREFIX,
style: Optional[Style] = None,
format: str = "%Y-%m-%d",
min_date: Optional[str] = None,
max_date: Optional[str] = None,
**kwargs: Any,
) -> Question:
"""
Prompt the user to enter a date.

This question type can be used to prompt the user for a date input,
with optional validation, formatting, and range restrictions.

Example:
>>> import questionary
>>> questionary.date("Enter your birthdate (YYYY-MM-DD):").ask()
? Enter your birthdate (YYYY-MM-DD): 1990-01-01
'1990-01-01'

Args:
message: Question text.

default: Default date value in the given format. Defaults to None.

validate: Custom validation function for the date input.
This can either be a function accepting the input and
returning a boolean, or a class reference to a
subclass of the prompt toolkit Validator class.

qmark: Question prefix displayed in front of the question.
By default this is a ``?``.

style: A custom color and style for the question parts. You can
configure colors as well as font types for different elements.

format: The expected date format (e.g., "%Y-%m-%d"). Defaults to "%Y-%m-%d".

min_date: The minimum allowed date in the given format. Defaults to None.

max_date: The maximum allowed date in the given format. Defaults to None.

kwargs: Additional arguments, they will be passed to prompt toolkit.

Returns:
:class:`Question`: Question instance, ready to be prompted (using ``.ask()``).
"""

def date_validator(input_date: str) -> bool:
"""Validate the entered date based on format and range."""
try:
parsed_date = datetime.strptime(input_date, format)

# Validate minimum date
if min_date:
min_date_obj = datetime.strptime(min_date, format)
if parsed_date < min_date_obj:
raise ValueError(
f"Date must not be earlier than {min_date}."
)

# Validate maximum date
if max_date:
max_date_obj = datetime.strptime(max_date, format)
if parsed_date > max_date_obj:
raise ValueError(
f"Date must not be later than {max_date}."
)

return True
except ValueError as e:
raise ValueError(str(e))

# Use the provided validator or the built-in date_validator
final_validator = validate or date_validator

return text.text(
message=message,
default=default,
validate=final_validator,
qmark=qmark,
style=style,
**kwargs,
)


25 changes: 25 additions & 0 deletions scripts/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import questionary

questionary.date(
"Which date do you want?",
format="%Y-%m-%d",
).ask()
questionary.text("What's your first name").ask()
questionary.password("What's your secret?").ask()
questionary.confirm("Are you amazed?").ask()

questionary.select(
"What do you want to do?",
choices=["Order a pizza", "Make a reservation", "Ask for opening hours"],
).ask()

questionary.rawselect(
"What do you want to do?",
choices=["Order a pizza", "Make a reservation", "Ask for opening hours"],
).ask()

questionary.checkbox(
"Select toppings", choices=["foo", "bar", "bazz"]
).ask()

questionary.path("Path to the projects version file").ask()
17 changes: 17 additions & 0 deletions tests/prompts/test_date.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import pytest
from prompt_toolkit.input.defaults import create_pipe_input
from prompt_toolkit.output import DummyOutput
from questionary.prompts.date import date


def test_date_prompt_with_default():
"""Test de saisie avec une valeur par défaut."""
with create_pipe_input() as pipe_input:
pipe_input.send_text("\n") # L'utilisateur appuie simplement sur Entrée
result = date(
"Enter a date (default is 2023-01-01):",
default="2023-01-01", # Définit une valeur par défaut valide
input=pipe_input,
output=DummyOutput()
).ask()
assert result == "2023-01-01"