diff -r b01e69847321 Doc/library/argparse.rst --- a/Doc/library/argparse.rst Tue Apr 07 07:10:38 2015 -0400 +++ b/Doc/library/argparse.rst Tue Apr 07 18:12:52 2015 +0100 @@ -1709,6 +1709,26 @@ Namespace(subparser_name='2', y='frobble') +DateType objects +^^^^^^^^^^^^^^^^ + +.. class:: DateType(format='%Y-%m-%d') + + The :class:`DateType` factory creates objects that can be passed to the type + argument of :meth:`ArgumentParser.add_argument`. Arguments that have + :class:`DateType` objects as their type will parse command-line arguments as + datetime.dates with the requested format (see the :class:`datetime.date` + class for more details):: + + >>> parser = argparse.ArgumentParser() + >>> parser.add_argument('--start', type=argparse.DateType('%d/%m/%Y)) + >>> parser.add_argument('end', type=argparse.DateType()) + >>> parser.parse_args(['--start', '01/02/2015', '2015-01-03']) + Namespace(end=datetime.date(2015, 1, 3), start=datetime.date(2015, 1, 2)) + + .. versionadded:: 3.5 + + FileType objects ^^^^^^^^^^^^^^^^ diff -r b01e69847321 Lib/argparse.py --- a/Lib/argparse.py Tue Apr 07 07:10:38 2015 -0400 +++ b/Lib/argparse.py Tue Apr 07 18:12:52 2015 +0100 @@ -19,6 +19,9 @@ parser.add_argument( '--log', default=sys.stdout, type=argparse.FileType('w'), help='the file where the sum should be written') + parse.add_argument( + '--date, default=date.today(), type=argparse.DateType('%m/%d/%Y'), + help='the date the integers were summed') args = parser.parse_args() args.log.write('%s' % sum(args.integers)) args.log.close() @@ -36,6 +39,10 @@ parsing the command-line are caught by ArgumentParser and emitted as command-line messages. + - DateType -- A factory for defining types of datetime.dates to be created. + As the example above shows, instances of DateType are typically passed + as the type= argument of add_argument() calls. + - FileType -- A factory for defining types of files to be created. As the example above shows, instances of FileType are typically passed as the type= argument of add_argument() calls. @@ -66,6 +73,7 @@ 'ArgumentParser', 'ArgumentError', 'ArgumentTypeError', + 'DateType', 'FileType', 'HelpFormatter', 'ArgumentDefaultsHelpFormatter', @@ -90,6 +98,7 @@ import sys as _sys import textwrap as _textwrap +from datetime import datetime as _datetime from gettext import gettext as _, ngettext @@ -1139,6 +1148,31 @@ # Type classes # ============== +class DateType(object): + """Factory for creating datetime.date object types + + Instances of DateType are typically passed as type= arguments to the + ArgumentParser add_argument() method. + + Keyword Arguments: + - format -- A string indicating how to parse the date string. Accepts + the same values as datetime.strptime + """ + + def __init__(self, format='%Y-%m-%d'): + self._format = format + + def __call__(self, date_string): + try: + return _datetime.strptime(date_string, self._format).date() + except ValueError as e: + message = _("can't parse '%s': %s") + raise ArgumentTypeError(message % (date_string, e)) + + def __repr__(self): + return '%s(%s)' % (type(self).__name__, repr(self._format)) + + class FileType(object): """Factory for creating file object types diff -r b01e69847321 Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py Tue Apr 07 07:10:38 2015 -0400 +++ b/Lib/test/test_argparse.py Tue Apr 07 18:12:52 2015 +0100 @@ -11,6 +11,7 @@ import unittest import argparse +from datetime import date from io import StringIO from test import support @@ -1436,6 +1437,13 @@ # Type conversion tests # ===================== +class TestDateTypeRepr(TestCase): + + def test_format(self): + type = argparse.DateType('%d/%m/%Y') + self.assertEqual("DateType('%d/%m/%Y')", repr(type)) + + class TestFileTypeRepr(TestCase): def test_r(self): @@ -1477,6 +1485,23 @@ return self.name == other.name == text +class TestDateType(ParserTestCase): + """Test that DateType parses date in the correct format""" + + argument_signatures = [ + Sig('-x', type=argparse.DateType()), + Sig('spam', type=argparse.DateType('%d/%m/%Y')) + ] + failures = ['-x', '', 'this is not a date', 'Tuesday 7th April'] + successes = [ + ('01/02/2015', NS(x=None, spam=date(2015, 2, 1))), + ('-x 2016-03-04 01/02/2015', NS(x=date(2016, 3, 4), spam=date(2015, 2, + 1))), + ('01/02/2015 -x 2016-03-04', NS(x=date(2016, 3, 4), spam=date(2015, 2, + 1))), + ] + + class TestFileTypeR(TempDirMixin, ParserTestCase): """Test the FileType option/argument type for reading files"""