commit 3fa25344f494e66071fd15f3719d796cf9ca3a67
parent 6a10ea8690415396c61a1cde9ff56f91d9ca2b41
Author: Carlosokumu <carlosokumu254@gmail.com>
Date: Mon, 1 Sep 2025 12:52:30 +0300
move datetime parsing to utils
Diffstat:
1 file changed, 14 insertions(+), 36 deletions(-)
diff --git a/ungana/cmd/args_parser.py b/ungana/cmd/args_parser.py
@@ -6,9 +6,12 @@ import logging
import sys
from ungana.attachment.attachment_manager import AttachmentManager
from ungana.ical.ical_manager import ICalManager
+from ungana.ical.ical_helper import ICalHelper
from ungana.logging.logging_manager import LoggingManager
from dateutil import tz
+from ungana.utils import validate_datetime, validate_duration
+
class ArgsParser:
EMAIL_RE = re.compile(r"^[^@]+@[^@]+\.[^@]+$")
@@ -27,31 +30,6 @@ class ArgsParser:
except Exception as e:
raise SystemExit(f"Error: Could not read file '{file_path}': {e}")
- def _validate_datetime(self, dt_str: str) -> str:
- try:
- dt = datetime.fromisoformat(dt_str)
- return dt.isoformat()
- except ValueError:
- pass
- try:
- dt = datetime.strptime(dt_str, "%d-%m-%Y %H:%M")
- return dt.isoformat()
- except ValueError:
- pass
-
- raise argparse.ArgumentTypeError(
- f"Invalid datetime format: '{dt_str}'. "
- "Expected ISO format (YYYY-MM-DDTHH:MM:SS+ZZ:ZZ) or DD-MM-YYYY HH:MM"
- )
-
- def _validate_duration(self, duration_str: str) -> str:
- """Validate duration format (e.g., '2h' or '30m')."""
- if not re.match(r'^(\d+h)?(\d+m)?$', duration_str):
- raise argparse.ArgumentTypeError(
- f"Invalid duration format: '{duration_str}'. Expected format like '2h' or '30m'"
- )
- return duration_str
-
def _add_command_arguments(self):
subparsers = self.parser.add_subparsers(dest='command', required=True)
@@ -74,7 +52,7 @@ class ArgsParser:
help="Run interactive calendar creation")
parser.add_argument("-s", "--summary", required=required, help="Event summary")
- parser.add_argument("--start", type=self._validate_datetime, required=required,help="Event start time (ISO format or DD-MM-YYYY HH:MM)")
+ parser.add_argument("--start", type=validate_datetime, required=required,help="Event start time (ISO format or DD-MM-YYYY HH:MM)")
parser.add_argument("-d", "--description",required=required, help="Event description")
parser.add_argument("-l", "--location",required=required,help="Event location")
parser.add_argument("-o", "--organizer",required=required,help="Event organizer")
@@ -82,8 +60,8 @@ class ArgsParser:
parser.add_argument("--sf", "--summary-file", dest="summary_file", help="File containing event summary")
parser.add_argument("--df", "--description-file", dest="description_file", help="File containing event description")
parser.add_argument("--tzid", help="Time zone ID")
- parser.add_argument("--duration", type=self._validate_duration, help="Event duration")
- parser.add_argument("--end", type=self._validate_datetime, help="Event end time")
+ parser.add_argument("--duration", type=validate_duration, help="Event duration")
+ parser.add_argument("--end", type=validate_datetime, help="Event end time")
def add_create_args(self, parser):
@@ -96,7 +74,7 @@ class ArgsParser:
non_interactive = parser.add_argument_group("non-interactive arguments")
non_interactive.add_argument("-s", "--summary", help="Event summary")
- non_interactive.add_argument("--start", type=self._validate_datetime, help="Event start time (ISO format or DD-MM-YYYY HH:MM)")
+ non_interactive.add_argument("--start", type=validate_datetime, help="Event start time (ISO format or DD-MM-YYYY HH:MM)")
non_interactive.add_argument("-d", "--description", help="Event description")
non_interactive.add_argument("-l", "--location", help="Event location")
non_interactive.add_argument("-o", "--organizer", help="Event organizer")
@@ -108,8 +86,8 @@ class ArgsParser:
parser.add_argument("--domain", help="Domain used to generate event UID (default: ungana.local)",default="ungana.local")
event_end_time_group = non_interactive.add_mutually_exclusive_group(required=False)
- event_end_time_group.add_argument("--end", type=self._validate_datetime,help="Event end time (ISO format or DD-MM-YYYY HH:MM). ""Required if no --duration is specified.",)
- event_end_time_group.add_argument( "--duration",type=self._validate_duration, help="Event duration (e.g shorthand like '1h30m'). Required if no --end is specified.",)
+ event_end_time_group.add_argument("--end", type=validate_datetime,help="Event end time (ISO format or DD-MM-YYYY HH:MM). ""Required if no --duration is specified.",)
+ event_end_time_group.add_argument( "--duration",type=validate_duration, help="Event duration (e.g shorthand like '1h30m'). Required if no --end is specified.",)
@@ -235,7 +213,7 @@ class ArgsParser:
if args.ics_filename:
filename = args.ics_filename
cal = self.ical_manager.load_ical_file(filename)
- exists = self.ical_manager.check_existing_event(cal, event_data)
+ exists = ICalHelper.check_existing_event(cal, event_data)
if exists:
details = (
f"Summary='{event_data['summary']}', "
@@ -271,7 +249,7 @@ class ArgsParser:
updates, attachments = self._get_user_updates_from_args(args)
if any([updates, attachments]):
# Non-interactive mode
- self.ical_manager.update_event(cal, updates, attachments, ical_file_path)
+ ICalHelper.update_event(cal, updates, attachments, ical_file_path)
logging.info("Calendar updated successfully")
else:
# Interactive mode
@@ -279,7 +257,7 @@ class ArgsParser:
def _edit_most_recent_event(self, cal, args, ical_file_path):
- event = self.ical_manager.get_first_event(cal)
+ event = ICalHelper.get_first_event(cal)
# only interactive prompts
updates = self._get_user_event_updates(event)
@@ -293,7 +271,7 @@ class ArgsParser:
def _edit_multiple_events(self, cal, ical_file_path):
"""Edit a specific event from multiple events (requires --all)."""
- events = self.ical_manager.get_all_events(cal)
+ events = ICalHelper.get_all_events(cal)
if not events:
self.parser.error("no events found for the selected ical file")
return
@@ -321,7 +299,7 @@ class ArgsParser:
updates = self._get_user_event_updates(event)
if updates:
- self.ical_manager.update_event(cal, updates, None, ical_file_path)
+ ICalHelper.update_event(cal, updates, None, ical_file_path)
logging.info("Calendar updated successfully")
else:
logging.info("No changes made to calendar file")