Add NLP, scheduler, generator, and describer modules
Some checks failed
CI / test (push) Has been cancelled
Some checks failed
CI / test (push) Has been cancelled
This commit is contained in:
266
src/cronparse/generator.py
Normal file
266
src/cronparse/generator.py
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
"""Interactive cron generator wizard module."""
|
||||||
|
|
||||||
|
import click
|
||||||
|
from typing import Dict, Any, List, Tuple
|
||||||
|
|
||||||
|
|
||||||
|
MINUTE_CHOICES = [
|
||||||
|
("Every minute", "*"),
|
||||||
|
("Every 5 minutes", "*/5"),
|
||||||
|
("Every 10 minutes", "*/10"),
|
||||||
|
("Every 15 minutes", "*/15"),
|
||||||
|
("Every 30 minutes", "0"),
|
||||||
|
("Specific minutes", "specific"),
|
||||||
|
]
|
||||||
|
|
||||||
|
HOUR_CHOICES = [
|
||||||
|
("Every hour", "*"),
|
||||||
|
("Every 2 hours", "*/2"),
|
||||||
|
("Every 4 hours", "*/4"),
|
||||||
|
("Every 6 hours", "*/6"),
|
||||||
|
("Every 12 hours", "*/12"),
|
||||||
|
("Specific hour", "specific"),
|
||||||
|
]
|
||||||
|
|
||||||
|
DAY_CHOICES = [
|
||||||
|
("Every day", "*"),
|
||||||
|
("Every 2 days", "*/2"),
|
||||||
|
("Every 3 days", "*/3"),
|
||||||
|
("Specific day of month", "specific"),
|
||||||
|
]
|
||||||
|
|
||||||
|
MONTH_CHOICES = [
|
||||||
|
("Every month", "*"),
|
||||||
|
("Every 2 months", "*/2"),
|
||||||
|
("Every 3 months", "*/3"),
|
||||||
|
("Every 6 months", "*/6"),
|
||||||
|
("Specific month", "specific"),
|
||||||
|
]
|
||||||
|
|
||||||
|
DOW_CHOICES = [
|
||||||
|
("Every day of week", "*"),
|
||||||
|
("Monday to Friday (weekdays)", "1-5"),
|
||||||
|
("Saturday and Sunday (weekend)", "0,6"),
|
||||||
|
("Specific day", "specific"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def prompt_minute() -> str:
|
||||||
|
"""Prompt user for minute selection."""
|
||||||
|
click.echo("\nMinute selection:")
|
||||||
|
for i, (desc, value) in enumerate(MINUTE_CHOICES, 1):
|
||||||
|
click.echo(f" {i}. {desc}")
|
||||||
|
|
||||||
|
choice = click.prompt("Select (1-6)", type=int, default=1)
|
||||||
|
|
||||||
|
if choice == 1:
|
||||||
|
return "*"
|
||||||
|
elif choice == 2:
|
||||||
|
return "*/5"
|
||||||
|
elif choice == 3:
|
||||||
|
return "*/10"
|
||||||
|
elif choice == 4:
|
||||||
|
return "*/15"
|
||||||
|
elif choice == 5:
|
||||||
|
return "0"
|
||||||
|
elif choice == 6:
|
||||||
|
minutes = prompt_specific_values("minute", 0, 59)
|
||||||
|
return ",".join(map(str, minutes))
|
||||||
|
else:
|
||||||
|
return "*"
|
||||||
|
|
||||||
|
|
||||||
|
def prompt_hour() -> str:
|
||||||
|
"""Prompt user for hour selection."""
|
||||||
|
click.echo("\nHour selection:")
|
||||||
|
for i, (desc, value) in enumerate(HOUR_CHOICES, 1):
|
||||||
|
click.echo(f" {i}. {desc}")
|
||||||
|
|
||||||
|
choice = click.prompt("Select (1-6)", type=int, default=1)
|
||||||
|
|
||||||
|
if choice == 1:
|
||||||
|
return "*"
|
||||||
|
elif choice == 2:
|
||||||
|
return "*/2"
|
||||||
|
elif choice == 3:
|
||||||
|
return "*/4"
|
||||||
|
elif choice == 4:
|
||||||
|
return "*/6"
|
||||||
|
elif choice == 5:
|
||||||
|
return "*/12"
|
||||||
|
elif choice == 6:
|
||||||
|
hours = prompt_specific_values("hour", 0, 23)
|
||||||
|
return ",".join(map(str, hours))
|
||||||
|
else:
|
||||||
|
return "*"
|
||||||
|
|
||||||
|
|
||||||
|
def prompt_day() -> str:
|
||||||
|
"""Prompt user for day of month selection."""
|
||||||
|
click.echo("\nDay of month selection:")
|
||||||
|
for i, (desc, value) in enumerate(DAY_CHOICES, 1):
|
||||||
|
click.echo(f" {i}. {desc}")
|
||||||
|
|
||||||
|
choice = click.prompt("Select (1-4)", type=int, default=1)
|
||||||
|
|
||||||
|
if choice == 1:
|
||||||
|
return "*"
|
||||||
|
elif choice == 2:
|
||||||
|
return "*/2"
|
||||||
|
elif choice == 3:
|
||||||
|
return "*/3"
|
||||||
|
elif choice == 4:
|
||||||
|
days = prompt_specific_values("day", 1, 31)
|
||||||
|
return ",".join(map(str, days))
|
||||||
|
else:
|
||||||
|
return "*"
|
||||||
|
|
||||||
|
|
||||||
|
def prompt_month() -> str:
|
||||||
|
"""Prompt user for month selection."""
|
||||||
|
click.echo("\nMonth selection:")
|
||||||
|
for i, (desc, value) in enumerate(MONTH_CHOICES, 1):
|
||||||
|
click.echo(f" {i}. {desc}")
|
||||||
|
|
||||||
|
choice = click.prompt("Select (1-5)", type=int, default=1)
|
||||||
|
|
||||||
|
if choice == 1:
|
||||||
|
return "*"
|
||||||
|
elif choice == 2:
|
||||||
|
return "*/2"
|
||||||
|
elif choice == 3:
|
||||||
|
return "*/3"
|
||||||
|
elif choice == 4:
|
||||||
|
return "*/6"
|
||||||
|
elif choice == 5:
|
||||||
|
months = prompt_specific_values("month", 1, 12)
|
||||||
|
return ",".join(map(str, months))
|
||||||
|
else:
|
||||||
|
return "*"
|
||||||
|
|
||||||
|
|
||||||
|
def prompt_dow() -> str:
|
||||||
|
"""Prompt user for day of week selection."""
|
||||||
|
click.echo("\nDay of week selection:")
|
||||||
|
for i, (desc, value) in enumerate(DOW_CHOICES, 1):
|
||||||
|
click.echo(f" {i}. {desc}")
|
||||||
|
|
||||||
|
choice = click.prompt("Select (1-4)", type=int, default=1)
|
||||||
|
|
||||||
|
if choice == 1:
|
||||||
|
return "*"
|
||||||
|
elif choice == 2:
|
||||||
|
return "1-5"
|
||||||
|
elif choice == 3:
|
||||||
|
return "0,6"
|
||||||
|
elif choice == 4:
|
||||||
|
days = prompt_specific_dow_values()
|
||||||
|
return ",".join(map(str, days))
|
||||||
|
else:
|
||||||
|
return "*"
|
||||||
|
|
||||||
|
|
||||||
|
def prompt_specific_values(name: str, min_val: int, max_val: int) -> List[int]:
|
||||||
|
"""Prompt user for specific values within a range.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Name of the field (for display).
|
||||||
|
min_val: Minimum value.
|
||||||
|
max_val: Maximum value.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of selected values.
|
||||||
|
"""
|
||||||
|
values = []
|
||||||
|
while True:
|
||||||
|
prompt_text = f"Enter {name} ({min_val}-{max_val}), or 'done' to finish"
|
||||||
|
value = click.prompt(prompt_text, type=str, default="done")
|
||||||
|
|
||||||
|
if value.lower() == "done":
|
||||||
|
if not values:
|
||||||
|
click.echo(f"No values selected. Using {min_val}.")
|
||||||
|
values = [min_val]
|
||||||
|
break
|
||||||
|
|
||||||
|
try:
|
||||||
|
val = int(value)
|
||||||
|
if min_val <= val <= max_val:
|
||||||
|
if val not in values:
|
||||||
|
values.append(val)
|
||||||
|
else:
|
||||||
|
click.echo(f" {val} already selected.")
|
||||||
|
else:
|
||||||
|
click.echo(f" Invalid {name}. Must be between {min_val} and {max_val}.")
|
||||||
|
except ValueError:
|
||||||
|
click.echo(" Invalid input. Enter a number or 'done'.")
|
||||||
|
|
||||||
|
return sorted(values)
|
||||||
|
|
||||||
|
|
||||||
|
def prompt_specific_dow_values() -> List[int]:
|
||||||
|
"""Prompt user for specific day of week values.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of selected day numbers (0=Sunday).
|
||||||
|
"""
|
||||||
|
click.echo(" Select days of week:")
|
||||||
|
click.echo(" 0 = Sunday 4 = Thursday")
|
||||||
|
click.echo(" 1 = Monday 5 = Friday")
|
||||||
|
click.echo(" 2 = Tuesday 6 = Saturday")
|
||||||
|
click.echo(" 3 = Wednesday")
|
||||||
|
|
||||||
|
values = []
|
||||||
|
while True:
|
||||||
|
prompt_text = "Enter day (0-6), or 'done' to finish"
|
||||||
|
value = click.prompt(prompt_text, type=str, default="done")
|
||||||
|
|
||||||
|
if value.lower() == "done":
|
||||||
|
if not values:
|
||||||
|
click.echo("No values selected. Using 0 (Sunday).")
|
||||||
|
values = [0]
|
||||||
|
break
|
||||||
|
|
||||||
|
try:
|
||||||
|
val = int(value)
|
||||||
|
if 0 <= val <= 6:
|
||||||
|
if val not in values:
|
||||||
|
values.append(val)
|
||||||
|
else:
|
||||||
|
click.echo(f" {val} already selected.")
|
||||||
|
else:
|
||||||
|
click.echo(" Invalid day. Must be between 0 and 6.")
|
||||||
|
except ValueError:
|
||||||
|
click.echo(" Invalid input. Enter a number or 'done'.")
|
||||||
|
|
||||||
|
return sorted(values)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_cron_interactive() -> Dict[str, Any]:
|
||||||
|
"""Run interactive wizard to generate a cron expression.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict with 'cron' and 'fields'.
|
||||||
|
"""
|
||||||
|
click.echo(click.style("Cron Expression Wizard", fg="cyan", bold=True))
|
||||||
|
click.echo("=" * 50)
|
||||||
|
click.echo("This wizard will help you create a cron expression.")
|
||||||
|
click.echo("Press Ctrl+C at any time to cancel.\n")
|
||||||
|
|
||||||
|
minute = prompt_minute()
|
||||||
|
hour = prompt_hour()
|
||||||
|
day = prompt_day()
|
||||||
|
month = prompt_month()
|
||||||
|
dow = prompt_dow()
|
||||||
|
|
||||||
|
cron = f"{minute} {hour} {day} {month} {dow}"
|
||||||
|
|
||||||
|
return {
|
||||||
|
"cron": cron,
|
||||||
|
"fields": {
|
||||||
|
"minute": minute,
|
||||||
|
"hour": hour,
|
||||||
|
"day": day,
|
||||||
|
"month": month,
|
||||||
|
"day_of_week": dow,
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user