0

I'm currently building a command line interface in Python 3 with the argparse module.

I have a situation where I need to define choices (e.g. "today", "yesterday", "week", ...) for an optional argparse argument -s of a subparser, but also allow a date string, but only if it can be successfully parsed as datetime.datetime with a predefined format (e.g. "%Y-%m-%d"), otherwise an exception would be raised.

parser.add_argument(
            "-s",
            "--start-date",
            type=str,
            default="today",
            choices=["today", "yesterday", "week", <date>],  # date should be accepted only if datetime.strptime(date, "%Y-%m-%d") is successful
            help="start date help",
        )

Is this somehow possible?

St4rb0y
  • 317
  • 3
  • 5
  • 22
  • Does this answer your question: https://stackoverflow.com/questions/21437258/how-do-i-parse-a-date-as-an-argument-with-argparse ? – Alexandru Placinta Mar 26 '22 at 17:51
  • @AlexandruPlacinta Only to a degree, because I also need to offer "today", "yesterday", etc. as options, which aren't datetime.datetimes yet, but strings that will be later interpreted as such. – St4rb0y Mar 26 '22 at 17:53
  • 1
    The idea is the same, though, see also https://stackoverflow.com/a/25470943/3001761 - you have a custom type function that takes a string and either returns a value or rejects the input by throwing an error. You'd do the interpreting as such here, so the rest of the program just deals with datetimes. – jonrsharpe Mar 26 '22 at 17:56
  • While use of a custom `type` function here is great, don't be afraid to accept a simple string, and do the testing/conversion after parsing. – hpaulj Mar 27 '22 at 18:36

1 Answers1

1

From my previous question, I believe this will suffice you, the custom function that validates your input. If it is the base case with today, yesterday, week, you return the strung, otherwise you try to parse the date object.

You can change it however you see fit, but this illustrates your need.

import argparse

def parse_date(s):
    if s.lower() in ["today", "yesterday", "week"]:
        return s
    
    return datetime.datetime.strptime(s, "%Y-%m-%d")

parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument(
            "-s",
            "--start-date",
            type=lambda s: parse_date(s),
            default="today",
            help="start date help",
        )